From b1ec44e1566e17c4f79d32142603768cb81e39bc Mon Sep 17 00:00:00 2001 From: Ben Karl Date: Thu, 19 Oct 2023 19:35:57 +0000 Subject: [PATCH] Changes for release v15_0. --- ChangeLog | 9 + .../approve_merchant_center_link.py | 5 + .../account_management/create_customer.py | 2 +- .../get_account_hierarchy.py | 2 +- .../account_management/get_change_details.py | 2 +- .../account_management/get_change_summary.py | 2 +- .../invite_user_with_access_role.py | 2 +- .../link_manager_to_client.py | 10 +- .../list_accessible_customers.py | 2 +- .../reject_merchant_center_link.py | 11 +- .../account_management/update_user_access.py | 8 +- .../advanced_operations/add_ad_customizer.py | 8 +- .../add_ad_group_bid_modifier.py | 5 +- .../advanced_operations/add_app_campaign.py | 10 +- .../add_bidding_data_exclusion.py | 2 +- .../add_bidding_seasonality_adjustment.py | 2 +- examples/advanced_operations/add_call_ad.py | 8 +- .../add_display_upload_ad.py | 2 +- .../add_dynamic_page_feed_asset.py | 10 +- .../add_dynamic_search_ads.py | 2 +- .../add_performance_max_campaign.py | 74 +- .../add_responsive_search_ad_full.py | 29 +- ...responsive_search_ad_with_ad_customizer.py | 8 +- .../advanced_operations/add_smart_campaign.py | 2 +- .../create_and_attach_shared_keyword_set.py | 8 +- ...ind_and_remove_criteria_from_shared_set.py | 2 +- .../get_ad_group_bid_modifiers.py | 2 +- .../use_cross_account_bidding_strategy.py | 2 +- .../use_portfolio_bidding_strategy.py | 14 +- examples/basic_operations/add_ad_groups.py | 2 +- examples/basic_operations/add_campaigns.py | 8 +- examples/basic_operations/get_campaigns.py | 3 +- .../get_responsive_search_ads.py | 2 +- examples/basic_operations/pause_ad.py | 2 +- examples/basic_operations/remove_campaign.py | 2 +- .../search_for_google_ads_fields.py | 2 +- examples/basic_operations/update_ad_group.py | 2 +- examples/basic_operations/update_campaign.py | 2 +- .../update_responsive_search_ad.py | 2 +- .../billing/add_account_budget_proposal.py | 9 +- examples/billing/add_billing_setup.py | 2 +- examples/billing/get_invoices.py | 2 +- .../add_campaign_labels.py | 2 +- .../add_complete_campaigns_using_batch_job.py | 2 +- .../campaign_management/create_experiment.py | 2 +- .../get_all_disapproved_ads.py | 2 +- .../campaign_management/set_ad_parameters.py | 2 +- .../update_campaign_criterion_bid_modifier.py | 9 +- examples/campaign_management/validate_ad.py | 2 +- .../get_campaigns.py | 2 +- .../handle_keyword_policy_violations.py | 2 +- .../error_handling/handle_partial_failure.py | 2 +- .../handle_rate_exceeded_error.py | 2 +- ..._responsive_search_ad_policy_violations.py | 2 +- .../add_affiliate_location_extensions.py | 15 +- ...dd_business_profile_location_extensions.py | 4 +- examples/extensions/add_call.py | 2 +- examples/extensions/add_geo_target.py | 8 +- examples/extensions/add_hotel_callout.py | 2 +- examples/extensions/add_image_extension.py | 10 +- .../extensions/add_lead_form_extension.py | 2 +- examples/extensions/add_prices.py | 2 +- examples/extensions/add_sitelinks.py | 2 +- .../extensions/add_sitelinks_using_assets.py | 2 +- .../migrate_promotion_feed_to_asset.py | 2 +- ...ire_sitelink_campaign_extension_setting.py | 20 +- examples/extensions/update_sitelink.py | 8 +- ...ate_sitelink_campaign_extension_setting.py | 22 +- examples/feeds/create_feed_item_set.py | 12 +- .../feeds/get_feed_items_of_feed_item_set.py | 8 +- examples/feeds/link_feed_item_set.py | 8 +- examples/feeds/remove_feed_items.py | 2 +- ...emove_flights_feed_item_attribute_value.py | 2 +- ...lights_feed_item_string_attribute_value.py | 2 +- examples/misc/campaign_report_to_csv.py | 2 +- ...gate_search_result_pages_caching_tokens.py | 5 +- examples/misc/set_custom_client_timeouts.py | 2 +- examples/misc/upload_image.py | 11 +- examples/misc/upload_image_asset.py | 2 +- examples/misc/upload_media_bundle.py | 10 +- examples/planning/forecast_reach.py | 2 +- .../planning/generate_forecast_metrics.py | 2 +- .../planning/generate_historical_metrics.py | 2 +- examples/planning/generate_keyword_ideas.py | 2 +- ..._ad_group_criterion_cpc_bid_simulations.py | 2 +- .../recommendations/apply_recommendation.py | 8 +- .../detect_and_apply_recommendations.py | 16 +- .../recommendations/dismiss_recommendation.py | 2 +- .../get_text_ad_recommendations.py | 2 +- examples/remarketing/add_conversion_action.py | 9 +- .../add_conversion_based_user_list.py | 8 +- examples/remarketing/add_custom_audience.py | 2 +- .../add_customer_match_user_list.py | 73 +- .../add_dynamic_remarketing_asset.py | 2 +- .../add_flexible_rule_user_list.py | 2 +- examples/remarketing/add_flights_feed.py | 2 +- examples/remarketing/add_logical_user_list.py | 6 +- ...ant_center_dynamic_remarketing_campaign.py | 13 +- examples/remarketing/add_real_estate_feed.py | 14 +- .../set_up_advanced_remarketing.py | 17 +- examples/remarketing/set_up_remarketing.py | 2 +- .../update_audience_target_restriction.py | 2 +- .../remarketing/upload_call_conversion.py | 33 +- .../upload_conversion_adjustment.py | 14 +- ... upload_enhanced_conversions_for_leads.py} | 174 +- ...=> upload_enhanced_conversions_for_web.py} | 185 +- .../remarketing/upload_offline_conversion.py | 39 +- .../upload_store_sales_transactions.py | 112 +- .../reporting/parallel_report_download.py | 2 +- examples/shopping_ads/add_listing_scope.py | 8 +- ...formance_max_product_listing_group_tree.py | 91 +- .../add_performance_max_retail_campaign.py | 30 +- .../shopping_ads/add_shopping_product_ad.py | 11 +- ...add_shopping_product_listing_group_tree.py | 11 +- ...t.py => get_product_category_constants.py} | 55 +- .../add_campaign_targeting_criteria.py | 12 +- .../add_customer_negative_criteria.py | 13 +- .../add_demographic_targeting_criteria.py | 16 +- .../get_geo_target_constants_by_names.py | 2 +- examples/travel/add_hotel_ad.py | 2 +- .../add_hotel_ad_group_bid_modifiers.py | 2 +- .../travel/add_hotel_listing_group_tree.py | 11 +- ...rformance_max_for_travel_goals_campaign.py | 11 +- examples/travel/add_things_to_do_ad.py | 2 +- google-ads.yaml | 4 +- google/ads/googleads/__init__.py | 12 +- google/ads/googleads/client.py | 15 +- google/ads/googleads/config.py | 11 +- google/ads/googleads/interceptors/helpers.py | 6 + .../interceptors/metadata_interceptor.py | 17 +- google/ads/googleads/oauth2.py | 4 +- google/ads/googleads/v15/__init__.py | 1947 +++++++ google/ads/googleads/v15/common/__init__.py | 315 ++ .../googleads/v15/common/services/__init__.py | 15 + .../googleads/v15/common/types/__init__.py | 15 + .../googleads/v15/common/types/ad_asset.py | 178 + .../v15/common/types/ad_type_infos.py | 1802 +++++++ .../v15/common/types/asset_policy.py | 143 + .../v15/common/types/asset_set_types.py | 354 ++ .../googleads/v15/common/types/asset_types.py | 2247 +++++++++ .../googleads/v15/common/types/asset_usage.py | 55 + .../googleads/v15/common/types/audiences.py | 469 ++ .../ads/googleads/v15/common/types/bidding.py | 459 ++ .../v15/common/types/click_location.py | 90 + .../ads/googleads/v15/common/types/consent.py | 58 + .../googleads/v15/common/types/criteria.py | 2035 ++++++++ .../types/criterion_category_availability.py | 168 + .../v15/common/types/custom_parameter.py | 60 + .../v15/common/types/customizer_value.py | 59 + .../ads/googleads/v15/common/types/dates.py | 109 + .../googleads/v15/common/types/extensions.py | 911 ++++ .../googleads/v15/common/types/feed_common.py | 59 + .../types/feed_item_set_filter_type_infos.py | 105 + .../v15/common/types/final_app_url.py | 68 + .../v15/common/types/frequency_cap.py | 114 + .../v15/common/types/keyword_plan_common.py | 324 ++ .../v15/common/types/lifecycle_goals.py | 68 + .../v15/common/types/local_services.py | 50 + .../v15/common/types/matching_function.py | 269 + .../googleads/v15/common/types/metric_goal.py | 59 + .../ads/googleads/v15/common/types/metrics.py | 2353 +++++++++ .../v15/common/types/offline_user_data.py | 776 +++ .../ads/googleads/v15/common/types/policy.py | 496 ++ .../v15/common/types/policy_summary.py | 68 + .../common/types/real_time_bidding_setting.py | 52 + .../googleads/v15/common/types/segments.py | 1171 +++++ .../googleads/v15/common/types/simulation.py | 755 +++ .../googleads/v15/common/types/tag_snippet.py | 84 + .../v15/common/types/targeting_setting.py | 137 + .../googleads/v15/common/types/text_label.py | 62 + .../v15/common/types/url_collection.py | 72 + .../googleads/v15/common/types/user_lists.py | 616 +++ .../ads/googleads/v15/common/types/value.py | 90 + google/ads/googleads/v15/enums/__init__.py | 356 ++ .../googleads/v15/enums/services/__init__.py | 15 + .../ads/googleads/v15/enums/types/__init__.py | 15 + .../enums/types/access_invitation_status.py | 46 + .../v15/enums/types/access_reason.py | 48 + .../googleads/v15/enums/types/access_role.py | 44 + .../types/account_budget_proposal_status.py | 45 + .../types/account_budget_proposal_type.py | 44 + .../v15/enums/types/account_budget_status.py | 43 + .../v15/enums/types/account_link_status.py | 51 + .../types/ad_customizer_placeholder_field.py | 44 + .../v15/enums/types/ad_destination_type.py | 51 + .../enums/types/ad_group_ad_rotation_mode.py | 45 + .../v15/enums/types/ad_group_ad_status.py | 46 + .../ad_group_criterion_approval_status.py | 47 + .../enums/types/ad_group_criterion_status.py | 43 + .../v15/enums/types/ad_group_status.py | 46 + .../v15/enums/types/ad_group_type.py | 61 + .../v15/enums/types/ad_network_type.py | 46 + .../types/ad_serving_optimization_status.py | 45 + .../googleads/v15/enums/types/ad_strength.py | 46 + .../ads/googleads/v15/enums/types/ad_type.py | 71 + .../types/advertising_channel_sub_type.py | 59 + .../enums/types/advertising_channel_type.py | 52 + ...filiate_location_feed_relationship_type.py | 46 + .../affiliate_location_placeholder_field.py | 51 + .../v15/enums/types/age_range_type.py | 52 + .../types/android_privacy_interaction_type.py | 43 + .../types/android_privacy_network_type.py | 43 + .../v15/enums/types/app_bidding_goal.py | 52 + .../v15/enums/types/app_campaign_app_store.py | 42 + ...app_campaign_bidding_strategy_goal_type.py | 49 + .../v15/enums/types/app_payment_model_type.py | 41 + .../v15/enums/types/app_placeholder_field.py | 48 + .../googleads/v15/enums/types/app_store.py | 45 + .../types/app_url_operating_system_type.py | 42 + .../enums/types/asset_automation_status.py | 42 + .../v15/enums/types/asset_automation_type.py | 41 + .../v15/enums/types/asset_field_type.py | 70 + .../enums/types/asset_group_primary_status.py | 52 + .../asset_group_primary_status_reason.py | 56 + .../asset_group_signal_approval_status.py | 50 + .../v15/enums/types/asset_group_status.py | 46 + .../enums/types/asset_link_primary_status.py | 56 + .../types/asset_link_primary_status_reason.py | 55 + .../v15/enums/types/asset_link_status.py | 46 + .../asset_offline_evaluation_error_reasons.py | 52 + .../enums/types/asset_performance_label.py | 50 + .../v15/enums/types/asset_set_asset_status.py | 45 + .../v15/enums/types/asset_set_link_status.py | 47 + .../v15/enums/types/asset_set_status.py | 45 + .../v15/enums/types/asset_set_type.py | 55 + .../googleads/v15/enums/types/asset_source.py | 45 + .../googleads/v15/enums/types/asset_type.py | 67 + .../v15/enums/types/async_action_status.py | 48 + .../v15/enums/types/attribution_model.py | 54 + .../types/audience_insights_dimension.py | 52 + .../v15/enums/types/audience_scope.py | 42 + .../v15/enums/types/audience_status.py | 42 + .../v15/enums/types/batch_job_status.py | 43 + .../v15/enums/types/bid_modifier_source.py | 42 + .../v15/enums/types/bidding_source.py | 46 + .../enums/types/bidding_strategy_status.py | 42 + .../types/bidding_strategy_system_status.py | 65 + .../v15/enums/types/bidding_strategy_type.py | 60 + .../v15/enums/types/billing_setup_status.py | 44 + .../enums/types/brand_safety_suitability.py | 46 + .../googleads/v15/enums/types/brand_state.py | 46 + .../budget_campaign_association_status.py | 47 + .../v15/enums/types/budget_delivery_method.py | 45 + .../v15/enums/types/budget_period.py | 42 + .../v15/enums/types/budget_status.py | 42 + .../googleads/v15/enums/types/budget_type.py | 44 + .../types/call_conversion_reporting_state.py | 46 + .../v15/enums/types/call_placeholder_field.py | 45 + .../v15/enums/types/call_to_action_type.py | 57 + .../types/call_tracking_display_location.py | 45 + .../googleads/v15/enums/types/call_type.py | 45 + .../enums/types/callout_placeholder_field.py | 41 + .../enums/types/campaign_criterion_status.py | 43 + .../v15/enums/types/campaign_draft_status.py | 48 + .../enums/types/campaign_experiment_type.py | 45 + .../v15/enums/types/campaign_group_status.py | 42 + .../enums/types/campaign_primary_status.py | 56 + .../types/campaign_primary_status_reason.py | 84 + .../enums/types/campaign_serving_status.py | 45 + .../enums/types/campaign_shared_set_status.py | 45 + .../v15/enums/types/campaign_status.py | 46 + .../enums/types/chain_relationship_type.py | 45 + .../v15/enums/types/change_client_type.py | 56 + .../enums/types/change_event_resource_type.py | 64 + .../enums/types/change_status_operation.py | 46 + .../types/change_status_resource_type.py | 62 + .../googleads/v15/enums/types/click_type.py | 94 + .../enums/types/combined_audience_status.py | 42 + .../v15/enums/types/consent_status.py | 42 + .../v15/enums/types/content_label_type.py | 60 + .../enums/types/conversion_action_category.py | 66 + .../types/conversion_action_counting_type.py | 48 + .../enums/types/conversion_action_status.py | 46 + .../v15/enums/types/conversion_action_type.py | 83 + .../enums/types/conversion_adjustment_type.py | 46 + .../conversion_attribution_event_type.py | 45 + .../conversion_custom_variable_status.py | 46 + .../types/conversion_environment_enum.py | 45 + .../v15/enums/types/conversion_lag_bucket.py | 64 + .../conversion_or_adjustment_lag_bucket.py | 88 + .../v15/enums/types/conversion_origin.py | 46 + .../types/conversion_tracking_status_enum.py | 47 + ...conversion_value_rule_primary_dimension.py | 52 + .../types/conversion_value_rule_set_status.py | 46 + .../types/conversion_value_rule_status.py | 46 + ...er_prior_engagement_type_and_ltv_bucket.py | 48 + ...rion_category_channel_availability_mode.py | 51 + ...erion_category_locale_availability_mode.py | 51 + .../types/criterion_system_serving_status.py | 45 + .../v15/enums/types/criterion_type.py | 79 + .../types/custom_audience_member_type.py | 44 + .../v15/enums/types/custom_audience_status.py | 42 + .../v15/enums/types/custom_audience_type.py | 44 + .../types/custom_conversion_goal_status.py | 45 + .../types/custom_interest_member_type.py | 42 + .../v15/enums/types/custom_interest_status.py | 42 + .../v15/enums/types/custom_interest_type.py | 42 + .../enums/types/custom_placeholder_field.py | 64 + .../customer_acquisition_optimization_mode.py | 46 + .../types/customer_match_upload_key_type.py | 46 + ...r_conversion_eligibility_failure_reason.py | 52 + .../v15/enums/types/customer_status.py | 47 + .../types/customizer_attribute_status.py | 45 + .../enums/types/customizer_attribute_type.py | 47 + .../enums/types/customizer_value_status.py | 45 + .../enums/types/data_driven_model_status.py | 44 + .../googleads/v15/enums/types/day_of_week.py | 50 + .../ads/googleads/v15/enums/types/device.py | 48 + .../enums/types/display_ad_format_setting.py | 43 + .../types/display_upload_product_type.py | 57 + .../v15/enums/types/distance_bucket.py | 72 + .../types/dsa_page_feed_criterion_field.py | 44 + .../types/education_placeholder_field.py | 61 + .../v15/enums/types/experiment_metric.py | 53 + .../types/experiment_metric_direction.py | 48 + .../v15/enums/types/experiment_status.py | 47 + .../v15/enums/types/experiment_type.py | 50 + .../enums/types/extension_setting_device.py | 42 + .../v15/enums/types/extension_type.py | 56 + .../enums/types/external_conversion_source.py | 73 + .../v15/enums/types/feed_attribute_type.py | 56 + .../feed_item_quality_approval_status.py | 47 + .../feed_item_quality_disapproval_reason.py | 63 + .../v15/enums/types/feed_item_set_status.py | 45 + .../types/feed_item_set_string_filter_type.py | 44 + .../v15/enums/types/feed_item_status.py | 45 + .../enums/types/feed_item_target_device.py | 44 + .../enums/types/feed_item_target_status.py | 45 + .../v15/enums/types/feed_item_target_type.py | 46 + .../types/feed_item_validation_status.py | 46 + .../v15/enums/types/feed_link_status.py | 45 + .../types/feed_mapping_criterion_type.py | 45 + .../v15/enums/types/feed_mapping_status.py | 45 + .../googleads/v15/enums/types/feed_origin.py | 45 + .../googleads/v15/enums/types/feed_status.py | 42 + .../enums/types/flight_placeholder_field.py | 61 + .../enums/types/frequency_cap_event_type.py | 47 + .../v15/enums/types/frequency_cap_level.py | 48 + .../enums/types/frequency_cap_time_unit.py | 46 + .../googleads/v15/enums/types/gender_type.py | 46 + .../enums/types/geo_target_constant_status.py | 42 + .../enums/types/geo_targeting_restriction.py | 43 + .../v15/enums/types/geo_targeting_type.py | 42 + .../v15/enums/types/goal_config_level.py | 45 + .../enums/types/google_ads_field_category.py | 48 + .../enums/types/google_ads_field_data_type.py | 53 + .../enums/types/google_voice_call_status.py | 45 + .../types/hotel_asset_suggestion_status.py | 46 + .../enums/types/hotel_date_selection_type.py | 45 + .../enums/types/hotel_placeholder_field.py | 64 + .../v15/enums/types/hotel_price_bucket.py | 47 + .../v15/enums/types/hotel_rate_type.py | 44 + .../types/hotel_reconciliation_status.py | 44 + .../enums/types/image_placeholder_field.py | 43 + .../v15/enums/types/income_range_type.py | 52 + .../v15/enums/types/interaction_event_type.py | 49 + .../v15/enums/types/interaction_type.py | 41 + .../googleads/v15/enums/types/invoice_type.py | 42 + .../v15/enums/types/job_placeholder_field.py | 61 + .../v15/enums/types/keyword_match_type.py | 43 + .../keyword_plan_aggregate_metric_type.py | 41 + .../types/keyword_plan_competition_level.py | 50 + .../types/keyword_plan_concept_group_type.py | 46 + .../types/keyword_plan_forecast_interval.py | 43 + .../types/keyword_plan_keyword_annotation.py | 44 + .../v15/enums/types/keyword_plan_network.py | 45 + .../googleads/v15/enums/types/label_status.py | 42 + .../types/lead_form_call_to_action_type.py | 56 + .../enums/types/lead_form_desired_intent.py | 44 + .../types/lead_form_field_user_input_type.py | 156 + ...ad_form_post_submit_call_to_action_type.py | 49 + .../types/legacy_app_install_ad_app_store.py | 48 + .../v15/enums/types/linked_account_type.py | 49 + .../v15/enums/types/linked_product_type.py | 49 + ...ing_group_filter_custom_attribute_index.py | 48 + .../listing_group_filter_listing_source.py | 47 + ...ing_group_filter_product_category_level.py | 48 + .../listing_group_filter_product_channel.py | 42 + .../listing_group_filter_product_condition.py | 43 + ...listing_group_filter_product_type_level.py | 45 + .../types/listing_group_filter_type_enum.py | 46 + .../v15/enums/types/listing_group_type.py | 42 + .../googleads/v15/enums/types/listing_type.py | 41 + .../enums/types/local_placeholder_field.py | 63 + .../types/local_services_conversation_type.py | 48 + ...cal_services_insurance_rejection_reason.py | 59 + .../enums/types/local_services_lead_status.py | 48 + .../enums/types/local_services_lead_type.py | 43 + ...local_services_license_rejection_reason.py | 52 + .../types/local_services_participant_type.py | 45 + ...l_services_verification_artifact_status.py | 50 + ...cal_services_verification_artifact_type.py | 48 + .../local_services_verification_status.py | 52 + ...ion_extension_targeting_criterion_field.py | 48 + .../types/location_group_radius_units.py | 48 + .../enums/types/location_ownership_type.py | 45 + .../enums/types/location_placeholder_field.py | 48 + .../v15/enums/types/location_source_type.py | 42 + .../types/location_string_filter_type.py | 44 + .../enums/types/lookalike_expansion_level.py | 45 + .../v15/enums/types/manager_link_status.py | 48 + .../types/matching_function_context_type.py | 46 + .../enums/types/matching_function_operator.py | 45 + .../googleads/v15/enums/types/media_type.py | 46 + .../enums/types/message_placeholder_field.py | 45 + .../googleads/v15/enums/types/mime_type.py | 52 + .../v15/enums/types/minute_of_hour.py | 44 + .../v15/enums/types/mobile_app_vendor.py | 45 + .../v15/enums/types/mobile_device_type.py | 42 + .../v15/enums/types/month_of_year.py | 55 + .../enums/types/negative_geo_target_type.py | 45 + ...fline_conversion_diagnostic_status_enum.py | 44 + .../types/offline_event_upload_client_enum.py | 43 + .../offline_user_data_job_failure_reason.py | 48 + .../offline_user_data_job_match_rate_range.py | 52 + .../types/offline_user_data_job_status.py | 47 + .../enums/types/offline_user_data_job_type.py | 47 + .../operating_system_version_operator_type.py | 42 + .../v15/enums/types/optimization_goal_type.py | 43 + .../v15/enums/types/parental_status_type.py | 46 + .../googleads/v15/enums/types/payment_mode.py | 44 + .../types/performance_max_upgrade_status.py | 44 + .../v15/enums/types/placeholder_type.py | 63 + .../v15/enums/types/placement_type.py | 46 + .../v15/enums/types/policy_approval_status.py | 51 + .../v15/enums/types/policy_review_status.py | 47 + .../enums/types/policy_topic_entry_type.py | 49 + ..._evidence_destination_mismatch_url_type.py | 50 + ...evidence_destination_not_working_device.py | 48 + ..._destination_not_working_dns_error_type.py | 47 + .../enums/types/positive_geo_target_type.py | 46 + .../types/price_extension_price_qualifier.py | 46 + .../enums/types/price_extension_price_unit.py | 46 + .../v15/enums/types/price_extension_type.py | 49 + .../enums/types/price_placeholder_field.py | 93 + .../v15/enums/types/product_category_level.py | 45 + .../v15/enums/types/product_category_state.py | 42 + .../v15/enums/types/product_channel.py | 42 + .../types/product_channel_exclusivity.py | 42 + .../v15/enums/types/product_condition.py | 43 + .../types/product_custom_attribute_index.py | 48 + .../types/product_link_invitation_status.py | 51 + .../v15/enums/types/product_type_level.py | 45 + .../promotion_extension_discount_modifier.py | 44 + .../types/promotion_extension_occasion.py | 82 + .../types/promotion_placeholder_field.py | 54 + .../v15/enums/types/proximity_radius_units.py | 42 + .../v15/enums/types/quality_score_bucket.py | 43 + .../v15/enums/types/reach_plan_age_range.py | 66 + .../v15/enums/types/reach_plan_network.py | 43 + .../v15/enums/types/reach_plan_surface.py | 49 + .../types/real_estate_placeholder_field.py | 62 + .../recommendation_subscription_status.py | 45 + .../v15/enums/types/recommendation_type.py | 89 + .../enums/types/resource_change_operation.py | 46 + .../v15/enums/types/resource_limit_type.py | 181 + .../v15/enums/types/response_content_type.py | 41 + .../types/search_engine_results_page_type.py | 43 + .../v15/enums/types/search_term_match_type.py | 50 + .../types/search_term_targeting_status.py | 49 + .../enums/types/seasonality_event_scope.py | 47 + .../enums/types/seasonality_event_status.py | 46 + .../enums/types/served_asset_field_type.py | 70 + .../v15/enums/types/shared_set_status.py | 42 + .../v15/enums/types/shared_set_type.py | 44 + ...roducts_to_campaign_recommendation_enum.py | 49 + .../types/simulation_modification_method.py | 48 + .../v15/enums/types/simulation_type.py | 51 + .../enums/types/sitelink_placeholder_field.py | 47 + .../types/sk_ad_network_ad_event_type.py | 43 + .../types/sk_ad_network_attribution_credit.py | 43 + .../sk_ad_network_coarse_conversion_value.py | 48 + .../enums/types/sk_ad_network_source_type.py | 43 + .../enums/types/sk_ad_network_user_type.py | 43 + google/ads/googleads/v15/enums/types/slot.py | 47 + .../smart_campaign_not_eligible_reason.py | 47 + .../v15/enums/types/smart_campaign_status.py | 49 + .../v15/enums/types/spending_limit_type.py | 43 + .../structured_snippet_placeholder_field.py | 42 + .../v15/enums/types/summary_row_setting.py | 43 + .../types/system_managed_entity_source.py | 44 + .../target_cpa_opt_in_recommendation_goal.py | 47 + .../enums/types/target_frequency_time_unit.py | 46 + .../types/target_impression_share_location.py | 47 + .../v15/enums/types/targeting_dimension.py | 48 + .../googleads/v15/enums/types/time_type.py | 44 + .../enums/types/tracking_code_page_format.py | 47 + .../v15/enums/types/tracking_code_type.py | 49 + .../enums/types/travel_placeholder_field.py | 64 + .../v15/enums/types/user_identifier_source.py | 48 + .../types/user_interest_taxonomy_type.py | 45 + .../enums/types/user_list_access_status.py | 42 + .../enums/types/user_list_closing_reason.py | 44 + .../types/user_list_crm_data_source_type.py | 43 + .../user_list_date_rule_item_operator.py | 44 + .../types/user_list_flexible_rule_operator.py | 42 + .../types/user_list_logical_rule_operator.py | 43 + .../types/user_list_membership_status.py | 46 + .../user_list_number_rule_item_operator.py | 48 + .../types/user_list_prepopulation_status.py | 43 + .../v15/enums/types/user_list_rule_type.py | 42 + .../v15/enums/types/user_list_size_range.py | 56 + .../user_list_string_rule_item_operator.py | 50 + .../v15/enums/types/user_list_type.py | 47 + .../v15/enums/types/value_rule_device_type.py | 46 + .../value_rule_geo_location_match_type.py | 45 + .../v15/enums/types/value_rule_operation.py | 46 + .../types/value_rule_set_attachment_type.py | 45 + .../enums/types/value_rule_set_dimension.py | 47 + .../types/vanity_pharma_display_url_mode.py | 44 + .../v15/enums/types/vanity_pharma_text.py | 56 + .../v15/enums/types/video_thumbnail.py | 48 + .../enums/types/webpage_condition_operand.py | 48 + .../enums/types/webpage_condition_operator.py | 45 + google/ads/googleads/v15/errors/__init__.py | 177 + .../googleads/v15/errors/services/__init__.py | 15 + .../googleads/v15/errors/types/__init__.py | 15 + .../errors/types/access_invitation_error.py | 51 + .../types/account_budget_proposal_error.py | 69 + .../v15/errors/types/account_link_error.py | 42 + .../v15/errors/types/ad_customizer_error.py | 45 + .../googleads/v15/errors/types/ad_error.py | 192 + .../v15/errors/types/ad_group_ad_error.py | 51 + .../types/ad_group_bid_modifier_error.py | 45 + .../ad_group_criterion_customizer_error.py | 46 + .../errors/types/ad_group_criterion_error.py | 71 + .../errors/types/ad_group_customizer_error.py | 43 + .../v15/errors/types/ad_group_error.py | 55 + .../v15/errors/types/ad_group_feed_error.py | 47 + .../v15/errors/types/ad_parameter_error.py | 42 + .../v15/errors/types/ad_sharing_error.py | 43 + .../googleads/v15/errors/types/adx_error.py | 41 + .../googleads/v15/errors/types/asset_error.py | 76 + .../errors/types/asset_group_asset_error.py | 47 + .../v15/errors/types/asset_group_error.py | 56 + .../asset_group_listing_group_filter_error.py | 59 + .../errors/types/asset_group_signal_error.py | 46 + .../v15/errors/types/asset_link_error.py | 65 + .../v15/errors/types/asset_set_asset_error.py | 47 + .../v15/errors/types/asset_set_error.py | 51 + .../v15/errors/types/asset_set_link_error.py | 45 + .../v15/errors/types/audience_error.py | 50 + .../errors/types/audience_insights_error.py | 44 + .../v15/errors/types/authentication_error.py | 61 + .../v15/errors/types/authorization_error.py | 55 + .../v15/errors/types/batch_job_error.py | 47 + .../v15/errors/types/bidding_error.py | 70 + .../errors/types/bidding_strategy_error.py | 48 + .../v15/errors/types/billing_setup_error.py | 60 + .../v15/errors/types/campaign_budget_error.py | 64 + .../types/campaign_conversion_goal_error.py | 45 + .../errors/types/campaign_criterion_error.py | 72 + .../errors/types/campaign_customizer_error.py | 43 + .../v15/errors/types/campaign_draft_error.py | 50 + .../v15/errors/types/campaign_error.py | 115 + .../errors/types/campaign_experiment_error.py | 53 + .../v15/errors/types/campaign_feed_error.py | 48 + .../types/campaign_lifecycle_goal_error.py | 54 + .../errors/types/campaign_shared_set_error.py | 44 + .../v15/errors/types/change_event_error.py | 45 + .../v15/errors/types/change_status_error.py | 45 + .../v15/errors/types/collection_size_error.py | 45 + .../v15/errors/types/context_error.py | 42 + .../errors/types/conversion_action_error.py | 54 + .../conversion_adjustment_upload_error.py | 70 + .../types/conversion_custom_variable_error.py | 46 + .../conversion_goal_campaign_config_error.py | 51 + .../errors/types/conversion_upload_error.py | 93 + .../types/conversion_value_rule_error.py | 55 + .../types/conversion_value_rule_set_error.py | 56 + .../v15/errors/types/country_code_error.py | 41 + .../v15/errors/types/criterion_error.py | 188 + .../v15/errors/types/currency_code_error.py | 41 + .../v15/errors/types/currency_error.py | 41 + .../v15/errors/types/custom_audience_error.py | 51 + .../types/custom_conversion_goal_error.py | 49 + .../v15/errors/types/custom_interest_error.py | 50 + .../types/customer_client_link_error.py | 51 + .../errors/types/customer_customizer_error.py | 43 + .../v15/errors/types/customer_error.py | 44 + .../v15/errors/types/customer_feed_error.py | 47 + .../types/customer_lifecycle_goal_error.py | 50 + .../types/customer_manager_link_error.py | 52 + ...d_network_conversion_value_schema_error.py | 49 + .../types/customer_user_access_error.py | 48 + .../types/customizer_attribute_error.py | 44 + .../v15/errors/types/database_error.py | 43 + .../googleads/v15/errors/types/date_error.py | 50 + .../v15/errors/types/date_range_error.py | 45 + .../v15/errors/types/distinct_error.py | 42 + .../googleads/v15/errors/types/enum_error.py | 41 + .../ads/googleads/v15/errors/types/errors.py | 2387 +++++++++ .../v15/errors/types/experiment_arm_error.py | 54 + .../v15/errors/types/experiment_error.py | 67 + .../errors/types/extension_feed_item_error.py | 88 + .../errors/types/extension_setting_error.py | 108 + .../types/feed_attribute_reference_error.py | 46 + .../googleads/v15/errors/types/feed_error.py | 63 + .../v15/errors/types/feed_item_error.py | 50 + .../v15/errors/types/feed_item_set_error.py | 47 + .../errors/types/feed_item_set_link_error.py | 45 + .../errors/types/feed_item_target_error.py | 51 + .../types/feed_item_validation_error.py | 148 + .../v15/errors/types/feed_mapping_error.py | 58 + .../googleads/v15/errors/types/field_error.py | 48 + .../v15/errors/types/field_mask_error.py | 44 + .../v15/errors/types/function_error.py | 56 + .../errors/types/function_parsing_error.py | 54 + .../geo_target_constant_suggestion_error.py | 49 + .../v15/errors/types/header_error.py | 42 + .../googleads/v15/errors/types/id_error.py | 41 + .../googleads/v15/errors/types/image_error.py | 79 + .../v15/errors/types/internal_error.py | 44 + .../v15/errors/types/invoice_error.py | 45 + .../types/keyword_plan_ad_group_error.py | 47 + .../keyword_plan_ad_group_keyword_error.py | 53 + .../types/keyword_plan_campaign_error.py | 51 + .../keyword_plan_campaign_keyword_error.py | 46 + .../v15/errors/types/keyword_plan_error.py | 59 + .../errors/types/keyword_plan_idea_error.py | 45 + .../googleads/v15/errors/types/label_error.py | 49 + .../v15/errors/types/language_code_error.py | 42 + .../v15/errors/types/list_operation_error.py | 42 + .../v15/errors/types/manager_link_error.py | 59 + .../v15/errors/types/media_bundle_error.py | 62 + .../v15/errors/types/media_file_error.py | 63 + .../v15/errors/types/media_upload_error.py | 77 + .../v15/errors/types/merchant_center_error.py | 45 + .../v15/errors/types/multiplier_error.py | 52 + .../v15/errors/types/mutate_error.py | 49 + .../types/new_resource_creation_error.py | 46 + .../v15/errors/types/not_allowlisted_error.py | 44 + .../v15/errors/types/not_empty_error.py | 41 + .../googleads/v15/errors/types/null_error.py | 41 + .../types/offline_user_data_job_error.py | 81 + .../types/operation_access_denied_error.py | 53 + .../v15/errors/types/operator_error.py | 41 + .../v15/errors/types/partial_failure_error.py | 44 + .../errors/types/payments_account_error.py | 44 + .../v15/errors/types/policy_finding_error.py | 42 + .../policy_validation_parameter_error.py | 48 + .../errors/types/policy_violation_error.py | 44 + .../v15/errors/types/product_link_error.py | 43 + .../types/product_link_invitation_error.py | 46 + .../googleads/v15/errors/types/query_error.py | 95 + .../googleads/v15/errors/types/quota_error.py | 43 + .../googleads/v15/errors/types/range_error.py | 42 + .../v15/errors/types/reach_plan_error.py | 46 + .../v15/errors/types/recommendation_error.py | 61 + .../recommendation_subscription_error.py | 43 + .../v15/errors/types/region_code_error.py | 41 + .../v15/errors/types/request_error.py | 65 + .../types/resource_access_denied_error.py | 44 + .../resource_count_limit_exceeded_error.py | 54 + .../errors/types/search_term_insight_error.py | 49 + .../v15/errors/types/setting_error.py | 58 + .../errors/types/shared_criterion_error.py | 44 + .../v15/errors/types/shared_set_error.py | 44 + .../v15/errors/types/size_limit_error.py | 42 + .../v15/errors/types/smart_campaign_error.py | 47 + .../v15/errors/types/string_format_error.py | 42 + .../v15/errors/types/string_length_error.py | 43 + .../third_party_app_analytics_link_error.py | 49 + .../v15/errors/types/time_zone_error.py | 41 + .../v15/errors/types/url_field_error.py | 93 + .../v15/errors/types/user_data_error.py | 43 + .../v15/errors/types/user_list_error.py | 73 + .../types/youtube_video_registration_error.py | 46 + .../ads/googleads/v15/resources/__init__.py | 245 + .../v15/resources/services/__init__.py | 15 + .../googleads/v15/resources/types/__init__.py | 15 + .../types/accessible_bidding_strategy.py | 336 ++ .../v15/resources/types/account_budget.py | 453 ++ .../types/account_budget_proposal.py | 284 ++ .../v15/resources/types/account_link.py | 259 + .../ads/googleads/v15/resources/types/ad.py | 477 ++ .../googleads/v15/resources/types/ad_group.py | 385 ++ .../v15/resources/types/ad_group_ad.py | 149 + .../ad_group_ad_asset_combination_view.py | 81 + .../resources/types/ad_group_ad_asset_view.py | 175 + .../v15/resources/types/ad_group_ad_label.py | 68 + .../v15/resources/types/ad_group_asset.py | 132 + .../v15/resources/types/ad_group_asset_set.py | 74 + .../resources/types/ad_group_audience_view.py | 51 + .../resources/types/ad_group_bid_modifier.py | 183 + .../v15/resources/types/ad_group_criterion.py | 701 +++ .../types/ad_group_criterion_customizer.py | 91 + .../types/ad_group_criterion_label.py | 69 + .../types/ad_group_criterion_simulation.py | 147 + .../resources/types/ad_group_customizer.py | 84 + .../types/ad_group_extension_setting.py | 97 + .../v15/resources/types/ad_group_feed.py | 104 + .../v15/resources/types/ad_group_label.py | 68 + .../resources/types/ad_group_simulation.py | 162 + .../v15/resources/types/ad_parameter.py | 102 + .../v15/resources/types/ad_schedule_view.py | 49 + .../v15/resources/types/age_range_view.py | 47 + ...roid_privacy_shared_key_google_ad_group.py | 104 + ...roid_privacy_shared_key_google_campaign.py | 86 + ..._privacy_shared_key_google_network_type.py | 100 + .../googleads/v15/resources/types/asset.py | 516 ++ .../resources/types/asset_field_type_view.py | 62 + .../v15/resources/types/asset_group.py | 153 + .../v15/resources/types/asset_group_asset.py | 155 + .../types/asset_group_listing_group_filter.py | 452 ++ .../types/asset_group_product_group_view.py | 62 + .../v15/resources/types/asset_group_signal.py | 119 + .../types/asset_group_top_combination_view.py | 77 + .../v15/resources/types/asset_set.py | 208 + .../v15/resources/types/asset_set_asset.py | 73 + .../resources/types/asset_set_type_view.py | 65 + .../googleads/v15/resources/types/audience.py | 131 + .../v15/resources/types/batch_job.py | 190 + .../resources/types/bidding_data_exclusion.py | 147 + .../types/bidding_seasonality_adjustment.py | 160 + .../v15/resources/types/bidding_strategy.py | 255 + .../types/bidding_strategy_simulation.py | 128 + .../v15/resources/types/billing_setup.py | 223 + .../v15/resources/types/call_view.py | 111 + .../googleads/v15/resources/types/campaign.py | 1320 +++++ .../v15/resources/types/campaign_asset.py | 140 + .../v15/resources/types/campaign_asset_set.py | 74 + .../resources/types/campaign_audience_view.py | 53 + .../resources/types/campaign_bid_modifier.py | 95 + .../v15/resources/types/campaign_budget.py | 278 + .../types/campaign_conversion_goal.py | 84 + .../v15/resources/types/campaign_criterion.py | 447 ++ .../resources/types/campaign_customizer.py | 84 + .../v15/resources/types/campaign_draft.py | 134 + .../types/campaign_extension_setting.py | 97 + .../v15/resources/types/campaign_feed.py | 104 + .../v15/resources/types/campaign_group.py | 78 + .../v15/resources/types/campaign_label.py | 68 + .../types/campaign_lifecycle_goal.py | 96 + .../types/campaign_search_term_insight.py | 82 + .../resources/types/campaign_shared_set.py | 88 + .../resources/types/campaign_simulation.py | 172 + .../v15/resources/types/carrier_constant.py | 79 + .../v15/resources/types/change_event.py | 361 ++ .../v15/resources/types/change_status.py | 230 + .../v15/resources/types/click_view.py | 140 + .../v15/resources/types/combined_audience.py | 81 + .../v15/resources/types/conversion_action.py | 437 ++ .../types/conversion_custom_variable.py | 102 + .../types/conversion_goal_campaign_config.py | 74 + .../resources/types/conversion_value_rule.py | 203 + .../types/conversion_value_rule_set.py | 130 + .../v15/resources/types/currency_constant.py | 90 + .../v15/resources/types/custom_audience.py | 174 + .../resources/types/custom_conversion_goal.py | 79 + .../v15/resources/types/custom_interest.py | 145 + .../googleads/v15/resources/types/customer.py | 577 +++ .../v15/resources/types/customer_asset.py | 125 + .../v15/resources/types/customer_asset_set.py | 74 + .../v15/resources/types/customer_client.py | 167 + .../resources/types/customer_client_link.py | 91 + .../types/customer_conversion_goal.py | 81 + .../resources/types/customer_customizer.py | 77 + .../types/customer_extension_setting.py | 82 + .../v15/resources/types/customer_feed.py | 94 + .../v15/resources/types/customer_label.py | 76 + .../types/customer_lifecycle_goal.py | 93 + .../resources/types/customer_manager_link.py | 80 + .../types/customer_negative_criterion.py | 144 + .../types/customer_search_term_insight.py | 73 + ...r_sk_ad_network_conversion_value_schema.py | 257 + .../resources/types/customer_user_access.py | 99 + .../types/customer_user_access_invitation.py | 90 + .../resources/types/customizer_attribute.py | 88 + .../resources/types/detail_placement_view.py | 110 + .../resources/types/detailed_demographic.py | 92 + .../resources/types/display_keyword_view.py | 47 + .../v15/resources/types/distance_view.py | 78 + .../v15/resources/types/domain_category.py | 145 + .../dynamic_search_ads_search_term_view.py | 127 + .../types/expanded_landing_page_view.py | 62 + .../v15/resources/types/experiment.py | 174 + .../v15/resources/types/experiment_arm.py | 97 + .../resources/types/extension_feed_item.py | 301 ++ .../ads/googleads/v15/resources/types/feed.py | 360 ++ .../v15/resources/types/feed_item.py | 424 ++ .../v15/resources/types/feed_item_set.py | 117 + .../v15/resources/types/feed_item_set_link.py | 58 + .../v15/resources/types/feed_item_target.py | 154 + .../v15/resources/types/feed_mapping.py | 411 ++ .../resources/types/feed_placeholder_view.py | 59 + .../v15/resources/types/gender_view.py | 47 + .../resources/types/geo_target_constant.py | 120 + .../v15/resources/types/geographic_view.py | 77 + .../v15/resources/types/google_ads_field.py | 178 + .../resources/types/group_placement_view.py | 96 + .../v15/resources/types/hotel_group_view.py | 47 + .../resources/types/hotel_performance_view.py | 47 + .../resources/types/hotel_reconciliation.py | 152 + .../v15/resources/types/income_range_view.py | 47 + .../googleads/v15/resources/types/invoice.py | 766 +++ .../v15/resources/types/keyword_plan.py | 125 + .../resources/types/keyword_plan_ad_group.py | 95 + .../types/keyword_plan_ad_group_keyword.py | 115 + .../resources/types/keyword_plan_campaign.py | 146 + .../types/keyword_plan_campaign_keyword.py | 103 + .../resources/types/keyword_theme_constant.py | 84 + .../v15/resources/types/keyword_view.py | 47 + .../googleads/v15/resources/types/label.py | 89 + .../v15/resources/types/landing_page_view.py | 61 + .../v15/resources/types/language_constant.py | 89 + .../types/lead_form_submission_data.py | 164 + .../v15/resources/types/life_event.py | 91 + .../resources/types/local_services_lead.py | 196 + .../types/local_services_lead_conversation.py | 159 + .../local_services_verification_artifact.py | 291 ++ .../v15/resources/types/location_view.py | 49 + .../resources/types/managed_placement_view.py | 47 + .../v15/resources/types/media_file.py | 302 ++ .../types/mobile_app_category_constant.py | 69 + .../resources/types/mobile_device_constant.py | 100 + ...ffline_conversion_upload_client_summary.py | 342 ++ .../resources/types/offline_user_data_job.py | 159 + .../operating_system_version_constant.py | 103 + .../types/paid_organic_search_term_view.py | 61 + .../resources/types/parental_status_view.py | 47 + .../v15/resources/types/payments_account.py | 115 + .../v15/resources/types/per_store_view.py | 57 + .../types/product_category_constant.py | 124 + .../v15/resources/types/product_group_view.py | 47 + .../v15/resources/types/product_link.py | 176 + .../types/product_link_invitation.py | 136 + .../resources/types/qualifying_question.py | 66 + .../v15/resources/types/recommendation.py | 1777 +++++++ .../types/recommendation_subscription.py | 100 + .../v15/resources/types/remarketing_action.py | 85 + .../v15/resources/types/search_term_view.py | 81 + .../v15/resources/types/shared_criterion.py | 155 + .../v15/resources/types/shared_set.py | 114 + .../types/shopping_performance_view.py | 53 + .../types/smart_campaign_search_term_view.py | 61 + .../resources/types/smart_campaign_setting.py | 177 + .../types/third_party_app_analytics_link.py | 65 + .../v15/resources/types/topic_constant.py | 84 + .../v15/resources/types/topic_view.py | 47 + .../types/travel_activity_group_view.py | 48 + .../types/travel_activity_performance_view.py | 48 + .../v15/resources/types/user_interest.py | 112 + .../v15/resources/types/user_list.py | 340 ++ .../v15/resources/types/user_location_view.py | 75 + .../googleads/v15/resources/types/video.py | 87 + .../v15/resources/types/webpage_view.py | 47 + google/ads/googleads/v15/services/__init__.py | 15 + .../v15/services/services/__init__.py | 15 + .../__init__.py | 18 + .../account_budget_proposal_service/client.py | 588 +++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 296 ++ .../services/account_link_service/__init__.py | 18 + .../services/account_link_service/client.py | 638 +++ .../transports/__init__.py | 30 + .../account_link_service/transports/base.py | 173 + .../account_link_service/transports/grpc.py | 316 ++ .../ad_group_ad_label_service/__init__.py | 18 + .../ad_group_ad_label_service/client.py | 578 +++ .../transports/__init__.py | 30 + .../transports/base.py | 156 + .../transports/grpc.py | 282 ++ .../services/ad_group_ad_service/__init__.py | 18 + .../services/ad_group_ad_service/client.py | 608 +++ .../transports/__init__.py | 30 + .../ad_group_ad_service/transports/base.py | 156 + .../ad_group_ad_service/transports/grpc.py | 294 ++ .../ad_group_asset_service/__init__.py | 18 + .../services/ad_group_asset_service/client.py | 573 +++ .../transports/__init__.py | 30 + .../ad_group_asset_service/transports/base.py | 156 + .../ad_group_asset_service/transports/grpc.py | 282 ++ .../ad_group_asset_set_service/__init__.py | 18 + .../ad_group_asset_set_service/client.py | 574 +++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 276 + .../ad_group_bid_modifier_service/__init__.py | 18 + .../ad_group_bid_modifier_service/client.py | 576 +++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 291 ++ .../__init__.py | 18 + .../client.py | 588 +++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 286 ++ .../__init__.py | 18 + .../client.py | 591 +++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 286 ++ .../ad_group_criterion_service/__init__.py | 18 + .../ad_group_criterion_service/client.py | 649 +++ .../transports/__init__.py | 30 + .../transports/base.py | 156 + .../transports/grpc.py | 292 ++ .../ad_group_customizer_service/__init__.py | 18 + .../ad_group_customizer_service/client.py | 583 +++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 276 + .../__init__.py | 18 + .../client.py | 600 +++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 297 ++ .../ad_group_feed_service/__init__.py | 18 + .../services/ad_group_feed_service/client.py | 574 +++ .../transports/__init__.py | 30 + .../ad_group_feed_service/transports/base.py | 156 + .../ad_group_feed_service/transports/grpc.py | 286 ++ .../ad_group_label_service/__init__.py | 18 + .../services/ad_group_label_service/client.py | 570 +++ .../transports/__init__.py | 30 + .../ad_group_label_service/transports/base.py | 156 + .../ad_group_label_service/transports/grpc.py | 282 ++ .../services/ad_group_service/__init__.py | 18 + .../services/ad_group_service/client.py | 576 +++ .../ad_group_service/transports/__init__.py | 30 + .../ad_group_service/transports/base.py | 156 + .../ad_group_service/transports/grpc.py | 289 ++ .../services/ad_parameter_service/__init__.py | 18 + .../services/ad_parameter_service/client.py | 555 ++ .../transports/__init__.py | 30 + .../ad_parameter_service/transports/base.py | 156 + .../ad_parameter_service/transports/grpc.py | 280 ++ .../services/services/ad_service/__init__.py | 18 + .../services/services/ad_service/client.py | 611 +++ .../ad_service/transports/__init__.py | 28 + .../services/ad_service/transports/base.py | 168 + .../services/ad_service/transports/grpc.py | 318 ++ .../asset_group_asset_service/__init__.py | 18 + .../asset_group_asset_service/client.py | 573 +++ .../transports/__init__.py | 30 + .../transports/base.py | 156 + .../transports/grpc.py | 276 + .../__init__.py | 18 + .../client.py | 569 +++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 286 ++ .../services/asset_group_service/__init__.py | 18 + .../services/asset_group_service/client.py | 543 ++ .../transports/__init__.py | 30 + .../asset_group_service/transports/base.py | 156 + .../asset_group_service/transports/grpc.py | 274 + .../asset_group_signal_service/__init__.py | 18 + .../asset_group_signal_service/client.py | 560 +++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 276 + .../services/asset_service/__init__.py | 18 + .../services/services/asset_service/client.py | 551 ++ .../asset_service/transports/__init__.py | 30 + .../services/asset_service/transports/base.py | 156 + .../services/asset_service/transports/grpc.py | 287 ++ .../asset_set_asset_service/__init__.py | 18 + .../asset_set_asset_service/client.py | 567 +++ .../transports/__init__.py | 30 + .../transports/base.py | 156 + .../transports/grpc.py | 276 + .../services/asset_set_service/__init__.py | 18 + .../services/asset_set_service/client.py | 521 ++ .../asset_set_service/transports/__init__.py | 30 + .../asset_set_service/transports/base.py | 156 + .../asset_set_service/transports/grpc.py | 274 + .../audience_insights_service/__init__.py | 18 + .../audience_insights_service/client.py | 959 ++++ .../transports/__init__.py | 30 + .../transports/base.py | 234 + .../transports/grpc.py | 436 ++ .../services/audience_service/__init__.py | 18 + .../services/audience_service/client.py | 540 ++ .../audience_service/transports/__init__.py | 30 + .../audience_service/transports/base.py | 156 + .../audience_service/transports/grpc.py | 275 + .../services/batch_job_service/__init__.py | 18 + .../services/batch_job_service/client.py | 2586 ++++++++++ .../services/batch_job_service/pagers.py | 81 + .../batch_job_service/transports/__init__.py | 30 + .../batch_job_service/transports/base.py | 210 + .../batch_job_service/transports/grpc.py | 408 ++ .../__init__.py | 18 + .../bidding_data_exclusion_service/client.py | 560 +++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 280 ++ .../__init__.py | 18 + .../client.py | 564 +++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 286 ++ .../bidding_strategy_service/__init__.py | 18 + .../bidding_strategy_service/client.py | 543 ++ .../transports/__init__.py | 30 + .../transports/base.py | 156 + .../transports/grpc.py | 289 ++ .../billing_setup_service/__init__.py | 18 + .../services/billing_setup_service/client.py | 547 ++ .../transports/__init__.py | 30 + .../billing_setup_service/transports/base.py | 156 + .../billing_setup_service/transports/grpc.py | 289 ++ .../brand_suggestion_service/__init__.py | 18 + .../brand_suggestion_service/client.py | 491 ++ .../transports/__init__.py | 30 + .../transports/base.py | 156 + .../transports/grpc.py | 274 + .../campaign_asset_service/__init__.py | 18 + .../services/campaign_asset_service/client.py | 575 +++ .../transports/__init__.py | 30 + .../campaign_asset_service/transports/base.py | 156 + .../campaign_asset_service/transports/grpc.py | 282 ++ .../campaign_asset_set_service/__init__.py | 18 + .../campaign_asset_set_service/client.py | 580 +++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 276 + .../campaign_bid_modifier_service/__init__.py | 18 + .../campaign_bid_modifier_service/client.py | 576 +++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 290 ++ .../campaign_budget_service/__init__.py | 18 + .../campaign_budget_service/client.py | 535 ++ .../transports/__init__.py | 30 + .../transports/base.py | 156 + .../transports/grpc.py | 285 ++ .../__init__.py | 18 + .../client.py | 565 +++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 281 ++ .../campaign_criterion_service/__init__.py | 18 + .../campaign_criterion_service/client.py | 625 +++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 290 ++ .../campaign_customizer_service/__init__.py | 18 + .../campaign_customizer_service/client.py | 584 +++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 278 + .../campaign_draft_service/__init__.py | 18 + .../services/campaign_draft_service/client.py | 787 +++ .../services/campaign_draft_service/pagers.py | 88 + .../transports/__init__.py | 30 + .../campaign_draft_service/transports/base.py | 195 + .../campaign_draft_service/transports/grpc.py | 384 ++ .../__init__.py | 18 + .../client.py | 599 +++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 296 ++ .../campaign_feed_service/__init__.py | 18 + .../services/campaign_feed_service/client.py | 575 +++ .../transports/__init__.py | 30 + .../campaign_feed_service/transports/base.py | 156 + .../campaign_feed_service/transports/grpc.py | 287 ++ .../campaign_group_service/__init__.py | 18 + .../services/campaign_group_service/client.py | 528 ++ .../transports/__init__.py | 30 + .../campaign_group_service/transports/base.py | 156 + .../campaign_group_service/transports/grpc.py | 276 + .../campaign_label_service/__init__.py | 18 + .../services/campaign_label_service/client.py | 573 +++ .../transports/__init__.py | 30 + .../campaign_label_service/transports/base.py | 156 + .../campaign_label_service/transports/grpc.py | 282 ++ .../__init__.py | 18 + .../campaign_lifecycle_goal_service/client.py | 552 ++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 287 ++ .../services/campaign_service/__init__.py | 18 + .../services/campaign_service/client.py | 697 +++ .../campaign_service/transports/__init__.py | 30 + .../campaign_service/transports/base.py | 156 + .../campaign_service/transports/grpc.py | 291 ++ .../campaign_shared_set_service/__init__.py | 18 + .../campaign_shared_set_service/client.py | 593 +++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 286 ++ .../conversion_action_service/__init__.py | 18 + .../conversion_action_service/client.py | 559 ++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 284 ++ .../__init__.py | 18 + .../client.py | 545 ++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 289 ++ .../__init__.py | 18 + .../client.py | 562 +++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 288 ++ .../__init__.py | 18 + .../client.py | 583 +++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 286 ++ .../conversion_upload_service/__init__.py | 18 + .../conversion_upload_service/client.py | 677 +++ .../transports/__init__.py | 30 + .../transports/base.py | 173 + .../transports/grpc.py | 316 ++ .../conversion_value_rule_service/__init__.py | 18 + .../conversion_value_rule_service/client.py | 616 +++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 280 ++ .../__init__.py | 18 + .../client.py | 597 +++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 283 ++ .../custom_audience_service/__init__.py | 18 + .../custom_audience_service/client.py | 533 ++ .../transports/__init__.py | 30 + .../transports/base.py | 156 + .../transports/grpc.py | 284 ++ .../__init__.py | 18 + .../custom_conversion_goal_service/client.py | 561 +++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 280 ++ .../custom_interest_service/__init__.py | 18 + .../custom_interest_service/client.py | 532 ++ .../transports/__init__.py | 30 + .../transports/base.py | 156 + .../transports/grpc.py | 283 ++ .../customer_asset_service/__init__.py | 18 + .../services/customer_asset_service/client.py | 552 ++ .../transports/__init__.py | 30 + .../customer_asset_service/transports/base.py | 156 + .../customer_asset_service/transports/grpc.py | 281 ++ .../customer_asset_set_service/__init__.py | 18 + .../customer_asset_set_service/client.py | 575 +++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 276 + .../customer_client_link_service/__init__.py | 18 + .../customer_client_link_service/client.py | 552 ++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 285 ++ .../__init__.py | 18 + .../client.py | 543 ++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 281 ++ .../customer_customizer_service/__init__.py | 18 + .../customer_customizer_service/client.py | 562 +++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 278 + .../__init__.py | 18 + .../client.py | 576 +++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 295 ++ .../customer_feed_service/__init__.py | 18 + .../services/customer_feed_service/client.py | 553 ++ .../transports/__init__.py | 30 + .../customer_feed_service/transports/base.py | 156 + .../customer_feed_service/transports/grpc.py | 287 ++ .../customer_label_service/__init__.py | 18 + .../services/customer_label_service/client.py | 565 +++ .../transports/__init__.py | 30 + .../customer_label_service/transports/base.py | 156 + .../customer_label_service/transports/grpc.py | 281 ++ .../__init__.py | 18 + .../customer_lifecycle_goal_service/client.py | 549 ++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 287 ++ .../customer_manager_link_service/__init__.py | 18 + .../customer_manager_link_service/client.py | 687 +++ .../transports/__init__.py | 30 + .../transports/base.py | 177 + .../transports/grpc.py | 324 ++ .../__init__.py | 18 + .../client.py | 563 +++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 288 ++ .../services/customer_service/__init__.py | 18 + .../services/customer_service/client.py | 687 +++ .../customer_service/transports/__init__.py | 30 + .../customer_service/transports/base.py | 190 + .../customer_service/transports/grpc.py | 352 ++ .../__init__.py | 18 + .../client.py | 510 ++ .../transports/__init__.py | 32 + .../transports/base.py | 162 + .../transports/grpc.py | 294 ++ .../__init__.py | 18 + .../client.py | 537 ++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 291 ++ .../customer_user_access_service/__init__.py | 18 + .../customer_user_access_service/client.py | 535 ++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 284 ++ .../customizer_attribute_service/__init__.py | 18 + .../customizer_attribute_service/client.py | 542 ++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 278 + .../experiment_arm_service/__init__.py | 18 + .../services/experiment_arm_service/client.py | 572 +++ .../transports/__init__.py | 30 + .../experiment_arm_service/transports/base.py | 156 + .../experiment_arm_service/transports/grpc.py | 281 ++ .../services/experiment_service/__init__.py | 18 + .../services/experiment_service/client.py | 1075 ++++ .../services/experiment_service/pagers.py | 88 + .../experiment_service/transports/__init__.py | 30 + .../experiment_service/transports/base.py | 236 + .../experiment_service/transports/grpc.py | 485 ++ .../extension_feed_item_service/__init__.py | 18 + .../extension_feed_item_service/client.py | 628 +++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 287 ++ .../services/feed_item_service/__init__.py | 18 + .../services/feed_item_service/client.py | 556 ++ .../feed_item_service/transports/__init__.py | 30 + .../feed_item_service/transports/base.py | 156 + .../feed_item_service/transports/grpc.py | 286 ++ .../feed_item_set_link_service/__init__.py | 18 + .../feed_item_set_link_service/client.py | 585 +++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 279 + .../feed_item_set_service/__init__.py | 18 + .../services/feed_item_set_service/client.py | 549 ++ .../transports/__init__.py | 30 + .../feed_item_set_service/transports/base.py | 156 + .../feed_item_set_service/transports/grpc.py | 281 ++ .../feed_item_target_service/__init__.py | 18 + .../feed_item_target_service/client.py | 620 +++ .../transports/__init__.py | 30 + .../transports/base.py | 156 + .../transports/grpc.py | 285 ++ .../services/feed_mapping_service/__init__.py | 18 + .../services/feed_mapping_service/client.py | 554 ++ .../transports/__init__.py | 30 + .../feed_mapping_service/transports/base.py | 156 + .../feed_mapping_service/transports/grpc.py | 284 ++ .../services/feed_service/__init__.py | 18 + .../services/services/feed_service/client.py | 525 ++ .../feed_service/transports/__init__.py | 30 + .../services/feed_service/transports/base.py | 156 + .../services/feed_service/transports/grpc.py | 284 ++ .../geo_target_constant_service/__init__.py | 18 + .../geo_target_constant_service/client.py | 487 ++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 281 ++ .../google_ads_field_service/__init__.py | 18 + .../google_ads_field_service/client.py | 596 +++ .../google_ads_field_service/pagers.py | 88 + .../transports/__init__.py | 30 + .../transports/base.py | 174 + .../transports/grpc.py | 314 ++ .../services/google_ads_service/__init__.py | 18 + .../services/google_ads_service/client.py | 4474 +++++++++++++++++ .../services/google_ads_service/pagers.py | 81 + .../google_ads_service/transports/__init__.py | 30 + .../google_ads_service/transports/base.py | 190 + .../google_ads_service/transports/grpc.py | 429 ++ .../services/invoice_service/__init__.py | 18 + .../services/invoice_service/client.py | 542 ++ .../invoice_service/transports/__init__.py | 30 + .../invoice_service/transports/base.py | 156 + .../invoice_service/transports/grpc.py | 280 ++ .../__init__.py | 18 + .../client.py | 576 +++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 296 ++ .../keyword_plan_ad_group_service/__init__.py | 18 + .../keyword_plan_ad_group_service/client.py | 572 +++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 288 ++ .../__init__.py | 18 + .../client.py | 574 +++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 297 ++ .../keyword_plan_campaign_service/__init__.py | 18 + .../keyword_plan_campaign_service/client.py | 602 +++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 288 ++ .../keyword_plan_idea_service/__init__.py | 18 + .../keyword_plan_idea_service/client.py | 707 +++ .../keyword_plan_idea_service/pagers.py | 89 + .../transports/__init__.py | 30 + .../transports/base.py | 211 + .../transports/grpc.py | 393 ++ .../services/keyword_plan_service/__init__.py | 18 + .../services/keyword_plan_service/client.py | 530 ++ .../transports/__init__.py | 30 + .../keyword_plan_service/transports/base.py | 156 + .../keyword_plan_service/transports/grpc.py | 281 ++ .../__init__.py | 18 + .../keyword_theme_constant_service/client.py | 490 ++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 284 ++ .../services/label_service/__init__.py | 18 + .../services/services/label_service/client.py | 527 ++ .../label_service/transports/__init__.py | 30 + .../services/label_service/transports/base.py | 156 + .../services/label_service/transports/grpc.py | 284 ++ .../offline_user_data_job_service/__init__.py | 18 + .../offline_user_data_job_service/client.py | 775 +++ .../transports/__init__.py | 30 + .../transports/base.py | 199 + .../transports/grpc.py | 382 ++ .../payments_account_service/__init__.py | 18 + .../payments_account_service/client.py | 530 ++ .../transports/__init__.py | 30 + .../transports/base.py | 156 + .../transports/grpc.py | 283 ++ .../__init__.py | 18 + .../product_link_invitation_service/client.py | 546 ++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 280 ++ .../services/product_link_service/__init__.py | 18 + .../services/product_link_service/client.py | 636 +++ .../transports/__init__.py | 30 + .../product_link_service/transports/base.py | 173 + .../product_link_service/transports/grpc.py | 313 ++ .../services/reach_plan_service/__init__.py | 18 + .../services/reach_plan_service/client.py | 661 +++ .../reach_plan_service/transports/__init__.py | 30 + .../reach_plan_service/transports/base.py | 190 + .../reach_plan_service/transports/grpc.py | 357 ++ .../recommendation_service/__init__.py | 18 + .../services/recommendation_service/client.py | 696 +++ .../transports/__init__.py | 30 + .../recommendation_service/transports/base.py | 173 + .../recommendation_service/transports/grpc.py | 316 ++ .../__init__.py | 18 + .../client.py | 545 ++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 291 ++ .../remarketing_action_service/__init__.py | 18 + .../remarketing_action_service/client.py | 545 ++ .../transports/__init__.py | 30 + .../transports/base.py | 158 + .../transports/grpc.py | 281 ++ .../shared_criterion_service/__init__.py | 18 + .../shared_criterion_service/client.py | 579 +++ .../transports/__init__.py | 30 + .../transports/base.py | 156 + .../transports/grpc.py | 286 ++ .../services/shared_set_service/__init__.py | 18 + .../services/shared_set_service/client.py | 532 ++ .../shared_set_service/transports/__init__.py | 30 + .../shared_set_service/transports/base.py | 156 + .../shared_set_service/transports/grpc.py | 285 ++ .../__init__.py | 18 + .../smart_campaign_setting_service/client.py | 652 +++ .../transports/__init__.py | 30 + .../transports/base.py | 179 + .../transports/grpc.py | 310 ++ .../__init__.py | 18 + .../smart_campaign_suggest_service/client.py | 659 +++ .../transports/__init__.py | 30 + .../transports/base.py | 200 + .../transports/grpc.py | 346 ++ .../__init__.py | 18 + .../client.py | 502 ++ .../transports/__init__.py | 30 + .../transports/base.py | 162 + .../transports/grpc.py | 291 ++ .../__init__.py | 18 + .../travel_asset_suggestion_service/client.py | 510 ++ .../transports/__init__.py | 30 + .../transports/base.py | 160 + .../transports/grpc.py | 282 ++ .../services/user_data_service/__init__.py | 18 + .../services/user_data_service/client.py | 472 ++ .../user_data_service/transports/__init__.py | 30 + .../user_data_service/transports/base.py | 156 + .../user_data_service/transports/grpc.py | 286 ++ .../services/user_list_service/__init__.py | 18 + .../services/user_list_service/client.py | 530 ++ .../user_list_service/transports/__init__.py | 30 + .../user_list_service/transports/base.py | 156 + .../user_list_service/transports/grpc.py | 283 ++ .../googleads/v15/services/types/__init__.py | 15 + .../types/account_budget_proposal_service.py | 153 + .../services/types/account_link_service.py | 205 + .../types/ad_group_ad_label_service.py | 158 + .../v15/services/types/ad_group_ad_service.py | 208 + .../services/types/ad_group_asset_service.py | 199 + .../types/ad_group_asset_set_service.py | 180 + .../types/ad_group_bid_modifier_service.py | 205 + .../ad_group_criterion_customizer_service.py | 184 + .../types/ad_group_criterion_label_service.py | 160 + .../types/ad_group_criterion_service.py | 221 + .../types/ad_group_customizer_service.py | 184 + .../ad_group_extension_setting_service.py | 208 + .../services/types/ad_group_feed_service.py | 199 + .../services/types/ad_group_label_service.py | 154 + .../v15/services/types/ad_group_service.py | 195 + .../services/types/ad_parameter_service.py | 198 + .../v15/services/types/ad_service.py | 195 + .../types/asset_group_asset_service.py | 177 + ...sset_group_listing_group_filter_service.py | 189 + .../v15/services/types/asset_group_service.py | 163 + .../types/asset_group_signal_service.py | 198 + .../v15/services/types/asset_service.py | 191 + .../services/types/asset_set_asset_service.py | 176 + .../v15/services/types/asset_set_service.py | 194 + .../types/audience_insights_service.py | 1152 +++++ .../v15/services/types/audience_service.py | 183 + .../v15/services/types/batch_job_service.py | 329 ++ .../types/bidding_data_exclusion_service.py | 205 + .../bidding_seasonality_adjustment_service.py | 203 + .../types/bidding_strategy_service.py | 203 + .../services/types/billing_setup_service.py | 124 + .../types/brand_suggestion_service.py | 122 + .../services/types/campaign_asset_service.py | 199 + .../types/campaign_asset_set_service.py | 180 + .../types/campaign_bid_modifier_service.py | 205 + .../services/types/campaign_budget_service.py | 203 + .../types/campaign_conversion_goal_service.py | 128 + .../types/campaign_criterion_service.py | 203 + .../types/campaign_customizer_service.py | 184 + .../services/types/campaign_draft_service.py | 290 ++ .../campaign_extension_setting_service.py | 208 + .../services/types/campaign_feed_service.py | 199 + .../services/types/campaign_group_service.py | 199 + .../services/types/campaign_label_service.py | 157 + .../types/campaign_lifecycle_goal_service.py | 136 + .../v15/services/types/campaign_service.py | 195 + .../types/campaign_shared_set_service.py | 183 + .../types/conversion_action_service.py | 205 + .../conversion_adjustment_upload_service.py | 383 ++ .../conversion_custom_variable_service.py | 198 + ...conversion_goal_campaign_config_service.py | 156 + .../types/conversion_upload_service.py | 745 +++ .../types/conversion_value_rule_service.py | 207 + .../conversion_value_rule_set_service.py | 205 + .../services/types/custom_audience_service.py | 156 + .../types/custom_conversion_goal_service.py | 183 + .../services/types/custom_interest_service.py | 144 + .../services/types/customer_asset_service.py | 199 + .../types/customer_asset_set_service.py | 180 + .../types/customer_client_link_service.py | 140 + .../types/customer_conversion_goal_service.py | 128 + .../types/customer_customizer_service.py | 184 + .../customer_extension_setting_service.py | 208 + .../services/types/customer_feed_service.py | 199 + .../services/types/customer_label_service.py | 157 + .../types/customer_lifecycle_goal_service.py | 135 + .../types/customer_manager_link_service.py | 195 + .../customer_negative_criterion_service.py | 185 + .../v15/services/types/customer_service.py | 244 + ...network_conversion_value_schema_service.py | 127 + ...customer_user_access_invitation_service.py | 128 + .../types/customer_user_access_service.py | 133 + .../types/customizer_attribute_service.py | 193 + .../services/types/experiment_arm_service.py | 196 + .../v15/services/types/experiment_service.py | 401 ++ .../types/extension_feed_item_service.py | 205 + .../v15/services/types/feed_item_service.py | 195 + .../types/feed_item_set_link_service.py | 160 + .../services/types/feed_item_set_service.py | 173 + .../types/feed_item_target_service.py | 181 + .../services/types/feed_mapping_service.py | 177 + .../v15/services/types/feed_service.py | 195 + .../types/geo_target_constant_service.py | 204 + .../types/google_ads_field_service.py | 123 + .../v15/services/types/google_ads_service.py | 3978 +++++++++++++++ .../v15/services/types/invoice_service.py | 94 + .../keyword_plan_ad_group_keyword_service.py | 189 + .../types/keyword_plan_ad_group_service.py | 182 + .../keyword_plan_campaign_keyword_service.py | 187 + .../types/keyword_plan_campaign_service.py | 180 + .../types/keyword_plan_idea_service.py | 1123 +++++ .../services/types/keyword_plan_service.py | 176 + .../types/keyword_theme_constant_service.py | 86 + .../v15/services/types/label_service.py | 195 + .../types/offline_user_data_job_service.py | 253 + .../types/payments_account_service.py | 69 + .../types/product_link_invitation_service.py | 80 + .../services/types/product_link_service.py | 122 + .../v15/services/types/reach_plan_service.py | 1285 +++++ .../services/types/recommendation_service.py | 970 ++++ .../recommendation_subscription_service.py | 203 + .../types/remarketing_action_service.py | 166 + .../types/shared_criterion_service.py | 181 + .../v15/services/types/shared_set_service.py | 197 + .../types/smart_campaign_setting_service.py | 395 ++ .../types/smart_campaign_suggest_service.py | 421 ++ .../third_party_app_analytics_link_service.py | 55 + .../types/travel_asset_suggestion_service.py | 192 + .../v15/services/types/user_data_service.py | 143 + .../v15/services/types/user_list_service.py | 174 + google/ads/googleads/v15/types/__init__.py | 15 + setup.py | 12 +- tests/client_test.py | 44 +- tests/config_test.py | 36 +- .../interceptors/logging_interceptor_test.py | 36 + .../interceptors/metadata_interceptor_test.py | 44 +- 1522 files changed, 232523 insertions(+), 525 deletions(-) rename examples/remarketing/{upload_conversion_with_identifiers.py => upload_enhanced_conversions_for_leads.py} (55%) rename examples/remarketing/{upload_conversion_enhancement.py => upload_enhanced_conversions_for_web.py} (55%) rename examples/shopping_ads/{get_product_bidding_category_constant.py => get_product_category_constants.py} (66%) create mode 100644 google/ads/googleads/v15/__init__.py create mode 100644 google/ads/googleads/v15/common/__init__.py create mode 100644 google/ads/googleads/v15/common/services/__init__.py create mode 100644 google/ads/googleads/v15/common/types/__init__.py create mode 100644 google/ads/googleads/v15/common/types/ad_asset.py create mode 100644 google/ads/googleads/v15/common/types/ad_type_infos.py create mode 100644 google/ads/googleads/v15/common/types/asset_policy.py create mode 100644 google/ads/googleads/v15/common/types/asset_set_types.py create mode 100644 google/ads/googleads/v15/common/types/asset_types.py create mode 100644 google/ads/googleads/v15/common/types/asset_usage.py create mode 100644 google/ads/googleads/v15/common/types/audiences.py create mode 100644 google/ads/googleads/v15/common/types/bidding.py create mode 100644 google/ads/googleads/v15/common/types/click_location.py create mode 100644 google/ads/googleads/v15/common/types/consent.py create mode 100644 google/ads/googleads/v15/common/types/criteria.py create mode 100644 google/ads/googleads/v15/common/types/criterion_category_availability.py create mode 100644 google/ads/googleads/v15/common/types/custom_parameter.py create mode 100644 google/ads/googleads/v15/common/types/customizer_value.py create mode 100644 google/ads/googleads/v15/common/types/dates.py create mode 100644 google/ads/googleads/v15/common/types/extensions.py create mode 100644 google/ads/googleads/v15/common/types/feed_common.py create mode 100644 google/ads/googleads/v15/common/types/feed_item_set_filter_type_infos.py create mode 100644 google/ads/googleads/v15/common/types/final_app_url.py create mode 100644 google/ads/googleads/v15/common/types/frequency_cap.py create mode 100644 google/ads/googleads/v15/common/types/keyword_plan_common.py create mode 100644 google/ads/googleads/v15/common/types/lifecycle_goals.py create mode 100644 google/ads/googleads/v15/common/types/local_services.py create mode 100644 google/ads/googleads/v15/common/types/matching_function.py create mode 100644 google/ads/googleads/v15/common/types/metric_goal.py create mode 100644 google/ads/googleads/v15/common/types/metrics.py create mode 100644 google/ads/googleads/v15/common/types/offline_user_data.py create mode 100644 google/ads/googleads/v15/common/types/policy.py create mode 100644 google/ads/googleads/v15/common/types/policy_summary.py create mode 100644 google/ads/googleads/v15/common/types/real_time_bidding_setting.py create mode 100644 google/ads/googleads/v15/common/types/segments.py create mode 100644 google/ads/googleads/v15/common/types/simulation.py create mode 100644 google/ads/googleads/v15/common/types/tag_snippet.py create mode 100644 google/ads/googleads/v15/common/types/targeting_setting.py create mode 100644 google/ads/googleads/v15/common/types/text_label.py create mode 100644 google/ads/googleads/v15/common/types/url_collection.py create mode 100644 google/ads/googleads/v15/common/types/user_lists.py create mode 100644 google/ads/googleads/v15/common/types/value.py create mode 100644 google/ads/googleads/v15/enums/__init__.py create mode 100644 google/ads/googleads/v15/enums/services/__init__.py create mode 100644 google/ads/googleads/v15/enums/types/__init__.py create mode 100644 google/ads/googleads/v15/enums/types/access_invitation_status.py create mode 100644 google/ads/googleads/v15/enums/types/access_reason.py create mode 100644 google/ads/googleads/v15/enums/types/access_role.py create mode 100644 google/ads/googleads/v15/enums/types/account_budget_proposal_status.py create mode 100644 google/ads/googleads/v15/enums/types/account_budget_proposal_type.py create mode 100644 google/ads/googleads/v15/enums/types/account_budget_status.py create mode 100644 google/ads/googleads/v15/enums/types/account_link_status.py create mode 100644 google/ads/googleads/v15/enums/types/ad_customizer_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/ad_destination_type.py create mode 100644 google/ads/googleads/v15/enums/types/ad_group_ad_rotation_mode.py create mode 100644 google/ads/googleads/v15/enums/types/ad_group_ad_status.py create mode 100644 google/ads/googleads/v15/enums/types/ad_group_criterion_approval_status.py create mode 100644 google/ads/googleads/v15/enums/types/ad_group_criterion_status.py create mode 100644 google/ads/googleads/v15/enums/types/ad_group_status.py create mode 100644 google/ads/googleads/v15/enums/types/ad_group_type.py create mode 100644 google/ads/googleads/v15/enums/types/ad_network_type.py create mode 100644 google/ads/googleads/v15/enums/types/ad_serving_optimization_status.py create mode 100644 google/ads/googleads/v15/enums/types/ad_strength.py create mode 100644 google/ads/googleads/v15/enums/types/ad_type.py create mode 100644 google/ads/googleads/v15/enums/types/advertising_channel_sub_type.py create mode 100644 google/ads/googleads/v15/enums/types/advertising_channel_type.py create mode 100644 google/ads/googleads/v15/enums/types/affiliate_location_feed_relationship_type.py create mode 100644 google/ads/googleads/v15/enums/types/affiliate_location_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/age_range_type.py create mode 100644 google/ads/googleads/v15/enums/types/android_privacy_interaction_type.py create mode 100644 google/ads/googleads/v15/enums/types/android_privacy_network_type.py create mode 100644 google/ads/googleads/v15/enums/types/app_bidding_goal.py create mode 100644 google/ads/googleads/v15/enums/types/app_campaign_app_store.py create mode 100644 google/ads/googleads/v15/enums/types/app_campaign_bidding_strategy_goal_type.py create mode 100644 google/ads/googleads/v15/enums/types/app_payment_model_type.py create mode 100644 google/ads/googleads/v15/enums/types/app_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/app_store.py create mode 100644 google/ads/googleads/v15/enums/types/app_url_operating_system_type.py create mode 100644 google/ads/googleads/v15/enums/types/asset_automation_status.py create mode 100644 google/ads/googleads/v15/enums/types/asset_automation_type.py create mode 100644 google/ads/googleads/v15/enums/types/asset_field_type.py create mode 100644 google/ads/googleads/v15/enums/types/asset_group_primary_status.py create mode 100644 google/ads/googleads/v15/enums/types/asset_group_primary_status_reason.py create mode 100644 google/ads/googleads/v15/enums/types/asset_group_signal_approval_status.py create mode 100644 google/ads/googleads/v15/enums/types/asset_group_status.py create mode 100644 google/ads/googleads/v15/enums/types/asset_link_primary_status.py create mode 100644 google/ads/googleads/v15/enums/types/asset_link_primary_status_reason.py create mode 100644 google/ads/googleads/v15/enums/types/asset_link_status.py create mode 100644 google/ads/googleads/v15/enums/types/asset_offline_evaluation_error_reasons.py create mode 100644 google/ads/googleads/v15/enums/types/asset_performance_label.py create mode 100644 google/ads/googleads/v15/enums/types/asset_set_asset_status.py create mode 100644 google/ads/googleads/v15/enums/types/asset_set_link_status.py create mode 100644 google/ads/googleads/v15/enums/types/asset_set_status.py create mode 100644 google/ads/googleads/v15/enums/types/asset_set_type.py create mode 100644 google/ads/googleads/v15/enums/types/asset_source.py create mode 100644 google/ads/googleads/v15/enums/types/asset_type.py create mode 100644 google/ads/googleads/v15/enums/types/async_action_status.py create mode 100644 google/ads/googleads/v15/enums/types/attribution_model.py create mode 100644 google/ads/googleads/v15/enums/types/audience_insights_dimension.py create mode 100644 google/ads/googleads/v15/enums/types/audience_scope.py create mode 100644 google/ads/googleads/v15/enums/types/audience_status.py create mode 100644 google/ads/googleads/v15/enums/types/batch_job_status.py create mode 100644 google/ads/googleads/v15/enums/types/bid_modifier_source.py create mode 100644 google/ads/googleads/v15/enums/types/bidding_source.py create mode 100644 google/ads/googleads/v15/enums/types/bidding_strategy_status.py create mode 100644 google/ads/googleads/v15/enums/types/bidding_strategy_system_status.py create mode 100644 google/ads/googleads/v15/enums/types/bidding_strategy_type.py create mode 100644 google/ads/googleads/v15/enums/types/billing_setup_status.py create mode 100644 google/ads/googleads/v15/enums/types/brand_safety_suitability.py create mode 100644 google/ads/googleads/v15/enums/types/brand_state.py create mode 100644 google/ads/googleads/v15/enums/types/budget_campaign_association_status.py create mode 100644 google/ads/googleads/v15/enums/types/budget_delivery_method.py create mode 100644 google/ads/googleads/v15/enums/types/budget_period.py create mode 100644 google/ads/googleads/v15/enums/types/budget_status.py create mode 100644 google/ads/googleads/v15/enums/types/budget_type.py create mode 100644 google/ads/googleads/v15/enums/types/call_conversion_reporting_state.py create mode 100644 google/ads/googleads/v15/enums/types/call_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/call_to_action_type.py create mode 100644 google/ads/googleads/v15/enums/types/call_tracking_display_location.py create mode 100644 google/ads/googleads/v15/enums/types/call_type.py create mode 100644 google/ads/googleads/v15/enums/types/callout_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/campaign_criterion_status.py create mode 100644 google/ads/googleads/v15/enums/types/campaign_draft_status.py create mode 100644 google/ads/googleads/v15/enums/types/campaign_experiment_type.py create mode 100644 google/ads/googleads/v15/enums/types/campaign_group_status.py create mode 100644 google/ads/googleads/v15/enums/types/campaign_primary_status.py create mode 100644 google/ads/googleads/v15/enums/types/campaign_primary_status_reason.py create mode 100644 google/ads/googleads/v15/enums/types/campaign_serving_status.py create mode 100644 google/ads/googleads/v15/enums/types/campaign_shared_set_status.py create mode 100644 google/ads/googleads/v15/enums/types/campaign_status.py create mode 100644 google/ads/googleads/v15/enums/types/chain_relationship_type.py create mode 100644 google/ads/googleads/v15/enums/types/change_client_type.py create mode 100644 google/ads/googleads/v15/enums/types/change_event_resource_type.py create mode 100644 google/ads/googleads/v15/enums/types/change_status_operation.py create mode 100644 google/ads/googleads/v15/enums/types/change_status_resource_type.py create mode 100644 google/ads/googleads/v15/enums/types/click_type.py create mode 100644 google/ads/googleads/v15/enums/types/combined_audience_status.py create mode 100644 google/ads/googleads/v15/enums/types/consent_status.py create mode 100644 google/ads/googleads/v15/enums/types/content_label_type.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_action_category.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_action_counting_type.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_action_status.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_action_type.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_adjustment_type.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_attribution_event_type.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_custom_variable_status.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_environment_enum.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_lag_bucket.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_or_adjustment_lag_bucket.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_origin.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_tracking_status_enum.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_value_rule_primary_dimension.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_value_rule_set_status.py create mode 100644 google/ads/googleads/v15/enums/types/conversion_value_rule_status.py create mode 100644 google/ads/googleads/v15/enums/types/converting_user_prior_engagement_type_and_ltv_bucket.py create mode 100644 google/ads/googleads/v15/enums/types/criterion_category_channel_availability_mode.py create mode 100644 google/ads/googleads/v15/enums/types/criterion_category_locale_availability_mode.py create mode 100644 google/ads/googleads/v15/enums/types/criterion_system_serving_status.py create mode 100644 google/ads/googleads/v15/enums/types/criterion_type.py create mode 100644 google/ads/googleads/v15/enums/types/custom_audience_member_type.py create mode 100644 google/ads/googleads/v15/enums/types/custom_audience_status.py create mode 100644 google/ads/googleads/v15/enums/types/custom_audience_type.py create mode 100644 google/ads/googleads/v15/enums/types/custom_conversion_goal_status.py create mode 100644 google/ads/googleads/v15/enums/types/custom_interest_member_type.py create mode 100644 google/ads/googleads/v15/enums/types/custom_interest_status.py create mode 100644 google/ads/googleads/v15/enums/types/custom_interest_type.py create mode 100644 google/ads/googleads/v15/enums/types/custom_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/customer_acquisition_optimization_mode.py create mode 100644 google/ads/googleads/v15/enums/types/customer_match_upload_key_type.py create mode 100644 google/ads/googleads/v15/enums/types/customer_pay_per_conversion_eligibility_failure_reason.py create mode 100644 google/ads/googleads/v15/enums/types/customer_status.py create mode 100644 google/ads/googleads/v15/enums/types/customizer_attribute_status.py create mode 100644 google/ads/googleads/v15/enums/types/customizer_attribute_type.py create mode 100644 google/ads/googleads/v15/enums/types/customizer_value_status.py create mode 100644 google/ads/googleads/v15/enums/types/data_driven_model_status.py create mode 100644 google/ads/googleads/v15/enums/types/day_of_week.py create mode 100644 google/ads/googleads/v15/enums/types/device.py create mode 100644 google/ads/googleads/v15/enums/types/display_ad_format_setting.py create mode 100644 google/ads/googleads/v15/enums/types/display_upload_product_type.py create mode 100644 google/ads/googleads/v15/enums/types/distance_bucket.py create mode 100644 google/ads/googleads/v15/enums/types/dsa_page_feed_criterion_field.py create mode 100644 google/ads/googleads/v15/enums/types/education_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/experiment_metric.py create mode 100644 google/ads/googleads/v15/enums/types/experiment_metric_direction.py create mode 100644 google/ads/googleads/v15/enums/types/experiment_status.py create mode 100644 google/ads/googleads/v15/enums/types/experiment_type.py create mode 100644 google/ads/googleads/v15/enums/types/extension_setting_device.py create mode 100644 google/ads/googleads/v15/enums/types/extension_type.py create mode 100644 google/ads/googleads/v15/enums/types/external_conversion_source.py create mode 100644 google/ads/googleads/v15/enums/types/feed_attribute_type.py create mode 100644 google/ads/googleads/v15/enums/types/feed_item_quality_approval_status.py create mode 100644 google/ads/googleads/v15/enums/types/feed_item_quality_disapproval_reason.py create mode 100644 google/ads/googleads/v15/enums/types/feed_item_set_status.py create mode 100644 google/ads/googleads/v15/enums/types/feed_item_set_string_filter_type.py create mode 100644 google/ads/googleads/v15/enums/types/feed_item_status.py create mode 100644 google/ads/googleads/v15/enums/types/feed_item_target_device.py create mode 100644 google/ads/googleads/v15/enums/types/feed_item_target_status.py create mode 100644 google/ads/googleads/v15/enums/types/feed_item_target_type.py create mode 100644 google/ads/googleads/v15/enums/types/feed_item_validation_status.py create mode 100644 google/ads/googleads/v15/enums/types/feed_link_status.py create mode 100644 google/ads/googleads/v15/enums/types/feed_mapping_criterion_type.py create mode 100644 google/ads/googleads/v15/enums/types/feed_mapping_status.py create mode 100644 google/ads/googleads/v15/enums/types/feed_origin.py create mode 100644 google/ads/googleads/v15/enums/types/feed_status.py create mode 100644 google/ads/googleads/v15/enums/types/flight_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/frequency_cap_event_type.py create mode 100644 google/ads/googleads/v15/enums/types/frequency_cap_level.py create mode 100644 google/ads/googleads/v15/enums/types/frequency_cap_time_unit.py create mode 100644 google/ads/googleads/v15/enums/types/gender_type.py create mode 100644 google/ads/googleads/v15/enums/types/geo_target_constant_status.py create mode 100644 google/ads/googleads/v15/enums/types/geo_targeting_restriction.py create mode 100644 google/ads/googleads/v15/enums/types/geo_targeting_type.py create mode 100644 google/ads/googleads/v15/enums/types/goal_config_level.py create mode 100644 google/ads/googleads/v15/enums/types/google_ads_field_category.py create mode 100644 google/ads/googleads/v15/enums/types/google_ads_field_data_type.py create mode 100644 google/ads/googleads/v15/enums/types/google_voice_call_status.py create mode 100644 google/ads/googleads/v15/enums/types/hotel_asset_suggestion_status.py create mode 100644 google/ads/googleads/v15/enums/types/hotel_date_selection_type.py create mode 100644 google/ads/googleads/v15/enums/types/hotel_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/hotel_price_bucket.py create mode 100644 google/ads/googleads/v15/enums/types/hotel_rate_type.py create mode 100644 google/ads/googleads/v15/enums/types/hotel_reconciliation_status.py create mode 100644 google/ads/googleads/v15/enums/types/image_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/income_range_type.py create mode 100644 google/ads/googleads/v15/enums/types/interaction_event_type.py create mode 100644 google/ads/googleads/v15/enums/types/interaction_type.py create mode 100644 google/ads/googleads/v15/enums/types/invoice_type.py create mode 100644 google/ads/googleads/v15/enums/types/job_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/keyword_match_type.py create mode 100644 google/ads/googleads/v15/enums/types/keyword_plan_aggregate_metric_type.py create mode 100644 google/ads/googleads/v15/enums/types/keyword_plan_competition_level.py create mode 100644 google/ads/googleads/v15/enums/types/keyword_plan_concept_group_type.py create mode 100644 google/ads/googleads/v15/enums/types/keyword_plan_forecast_interval.py create mode 100644 google/ads/googleads/v15/enums/types/keyword_plan_keyword_annotation.py create mode 100644 google/ads/googleads/v15/enums/types/keyword_plan_network.py create mode 100644 google/ads/googleads/v15/enums/types/label_status.py create mode 100644 google/ads/googleads/v15/enums/types/lead_form_call_to_action_type.py create mode 100644 google/ads/googleads/v15/enums/types/lead_form_desired_intent.py create mode 100644 google/ads/googleads/v15/enums/types/lead_form_field_user_input_type.py create mode 100644 google/ads/googleads/v15/enums/types/lead_form_post_submit_call_to_action_type.py create mode 100644 google/ads/googleads/v15/enums/types/legacy_app_install_ad_app_store.py create mode 100644 google/ads/googleads/v15/enums/types/linked_account_type.py create mode 100644 google/ads/googleads/v15/enums/types/linked_product_type.py create mode 100644 google/ads/googleads/v15/enums/types/listing_group_filter_custom_attribute_index.py create mode 100644 google/ads/googleads/v15/enums/types/listing_group_filter_listing_source.py create mode 100644 google/ads/googleads/v15/enums/types/listing_group_filter_product_category_level.py create mode 100644 google/ads/googleads/v15/enums/types/listing_group_filter_product_channel.py create mode 100644 google/ads/googleads/v15/enums/types/listing_group_filter_product_condition.py create mode 100644 google/ads/googleads/v15/enums/types/listing_group_filter_product_type_level.py create mode 100644 google/ads/googleads/v15/enums/types/listing_group_filter_type_enum.py create mode 100644 google/ads/googleads/v15/enums/types/listing_group_type.py create mode 100644 google/ads/googleads/v15/enums/types/listing_type.py create mode 100644 google/ads/googleads/v15/enums/types/local_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/local_services_conversation_type.py create mode 100644 google/ads/googleads/v15/enums/types/local_services_insurance_rejection_reason.py create mode 100644 google/ads/googleads/v15/enums/types/local_services_lead_status.py create mode 100644 google/ads/googleads/v15/enums/types/local_services_lead_type.py create mode 100644 google/ads/googleads/v15/enums/types/local_services_license_rejection_reason.py create mode 100644 google/ads/googleads/v15/enums/types/local_services_participant_type.py create mode 100644 google/ads/googleads/v15/enums/types/local_services_verification_artifact_status.py create mode 100644 google/ads/googleads/v15/enums/types/local_services_verification_artifact_type.py create mode 100644 google/ads/googleads/v15/enums/types/local_services_verification_status.py create mode 100644 google/ads/googleads/v15/enums/types/location_extension_targeting_criterion_field.py create mode 100644 google/ads/googleads/v15/enums/types/location_group_radius_units.py create mode 100644 google/ads/googleads/v15/enums/types/location_ownership_type.py create mode 100644 google/ads/googleads/v15/enums/types/location_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/location_source_type.py create mode 100644 google/ads/googleads/v15/enums/types/location_string_filter_type.py create mode 100644 google/ads/googleads/v15/enums/types/lookalike_expansion_level.py create mode 100644 google/ads/googleads/v15/enums/types/manager_link_status.py create mode 100644 google/ads/googleads/v15/enums/types/matching_function_context_type.py create mode 100644 google/ads/googleads/v15/enums/types/matching_function_operator.py create mode 100644 google/ads/googleads/v15/enums/types/media_type.py create mode 100644 google/ads/googleads/v15/enums/types/message_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/mime_type.py create mode 100644 google/ads/googleads/v15/enums/types/minute_of_hour.py create mode 100644 google/ads/googleads/v15/enums/types/mobile_app_vendor.py create mode 100644 google/ads/googleads/v15/enums/types/mobile_device_type.py create mode 100644 google/ads/googleads/v15/enums/types/month_of_year.py create mode 100644 google/ads/googleads/v15/enums/types/negative_geo_target_type.py create mode 100644 google/ads/googleads/v15/enums/types/offline_conversion_diagnostic_status_enum.py create mode 100644 google/ads/googleads/v15/enums/types/offline_event_upload_client_enum.py create mode 100644 google/ads/googleads/v15/enums/types/offline_user_data_job_failure_reason.py create mode 100644 google/ads/googleads/v15/enums/types/offline_user_data_job_match_rate_range.py create mode 100644 google/ads/googleads/v15/enums/types/offline_user_data_job_status.py create mode 100644 google/ads/googleads/v15/enums/types/offline_user_data_job_type.py create mode 100644 google/ads/googleads/v15/enums/types/operating_system_version_operator_type.py create mode 100644 google/ads/googleads/v15/enums/types/optimization_goal_type.py create mode 100644 google/ads/googleads/v15/enums/types/parental_status_type.py create mode 100644 google/ads/googleads/v15/enums/types/payment_mode.py create mode 100644 google/ads/googleads/v15/enums/types/performance_max_upgrade_status.py create mode 100644 google/ads/googleads/v15/enums/types/placeholder_type.py create mode 100644 google/ads/googleads/v15/enums/types/placement_type.py create mode 100644 google/ads/googleads/v15/enums/types/policy_approval_status.py create mode 100644 google/ads/googleads/v15/enums/types/policy_review_status.py create mode 100644 google/ads/googleads/v15/enums/types/policy_topic_entry_type.py create mode 100644 google/ads/googleads/v15/enums/types/policy_topic_evidence_destination_mismatch_url_type.py create mode 100644 google/ads/googleads/v15/enums/types/policy_topic_evidence_destination_not_working_device.py create mode 100644 google/ads/googleads/v15/enums/types/policy_topic_evidence_destination_not_working_dns_error_type.py create mode 100644 google/ads/googleads/v15/enums/types/positive_geo_target_type.py create mode 100644 google/ads/googleads/v15/enums/types/price_extension_price_qualifier.py create mode 100644 google/ads/googleads/v15/enums/types/price_extension_price_unit.py create mode 100644 google/ads/googleads/v15/enums/types/price_extension_type.py create mode 100644 google/ads/googleads/v15/enums/types/price_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/product_category_level.py create mode 100644 google/ads/googleads/v15/enums/types/product_category_state.py create mode 100644 google/ads/googleads/v15/enums/types/product_channel.py create mode 100644 google/ads/googleads/v15/enums/types/product_channel_exclusivity.py create mode 100644 google/ads/googleads/v15/enums/types/product_condition.py create mode 100644 google/ads/googleads/v15/enums/types/product_custom_attribute_index.py create mode 100644 google/ads/googleads/v15/enums/types/product_link_invitation_status.py create mode 100644 google/ads/googleads/v15/enums/types/product_type_level.py create mode 100644 google/ads/googleads/v15/enums/types/promotion_extension_discount_modifier.py create mode 100644 google/ads/googleads/v15/enums/types/promotion_extension_occasion.py create mode 100644 google/ads/googleads/v15/enums/types/promotion_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/proximity_radius_units.py create mode 100644 google/ads/googleads/v15/enums/types/quality_score_bucket.py create mode 100644 google/ads/googleads/v15/enums/types/reach_plan_age_range.py create mode 100644 google/ads/googleads/v15/enums/types/reach_plan_network.py create mode 100644 google/ads/googleads/v15/enums/types/reach_plan_surface.py create mode 100644 google/ads/googleads/v15/enums/types/real_estate_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/recommendation_subscription_status.py create mode 100644 google/ads/googleads/v15/enums/types/recommendation_type.py create mode 100644 google/ads/googleads/v15/enums/types/resource_change_operation.py create mode 100644 google/ads/googleads/v15/enums/types/resource_limit_type.py create mode 100644 google/ads/googleads/v15/enums/types/response_content_type.py create mode 100644 google/ads/googleads/v15/enums/types/search_engine_results_page_type.py create mode 100644 google/ads/googleads/v15/enums/types/search_term_match_type.py create mode 100644 google/ads/googleads/v15/enums/types/search_term_targeting_status.py create mode 100644 google/ads/googleads/v15/enums/types/seasonality_event_scope.py create mode 100644 google/ads/googleads/v15/enums/types/seasonality_event_status.py create mode 100644 google/ads/googleads/v15/enums/types/served_asset_field_type.py create mode 100644 google/ads/googleads/v15/enums/types/shared_set_status.py create mode 100644 google/ads/googleads/v15/enums/types/shared_set_type.py create mode 100644 google/ads/googleads/v15/enums/types/shopping_add_products_to_campaign_recommendation_enum.py create mode 100644 google/ads/googleads/v15/enums/types/simulation_modification_method.py create mode 100644 google/ads/googleads/v15/enums/types/simulation_type.py create mode 100644 google/ads/googleads/v15/enums/types/sitelink_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/sk_ad_network_ad_event_type.py create mode 100644 google/ads/googleads/v15/enums/types/sk_ad_network_attribution_credit.py create mode 100644 google/ads/googleads/v15/enums/types/sk_ad_network_coarse_conversion_value.py create mode 100644 google/ads/googleads/v15/enums/types/sk_ad_network_source_type.py create mode 100644 google/ads/googleads/v15/enums/types/sk_ad_network_user_type.py create mode 100644 google/ads/googleads/v15/enums/types/slot.py create mode 100644 google/ads/googleads/v15/enums/types/smart_campaign_not_eligible_reason.py create mode 100644 google/ads/googleads/v15/enums/types/smart_campaign_status.py create mode 100644 google/ads/googleads/v15/enums/types/spending_limit_type.py create mode 100644 google/ads/googleads/v15/enums/types/structured_snippet_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/summary_row_setting.py create mode 100644 google/ads/googleads/v15/enums/types/system_managed_entity_source.py create mode 100644 google/ads/googleads/v15/enums/types/target_cpa_opt_in_recommendation_goal.py create mode 100644 google/ads/googleads/v15/enums/types/target_frequency_time_unit.py create mode 100644 google/ads/googleads/v15/enums/types/target_impression_share_location.py create mode 100644 google/ads/googleads/v15/enums/types/targeting_dimension.py create mode 100644 google/ads/googleads/v15/enums/types/time_type.py create mode 100644 google/ads/googleads/v15/enums/types/tracking_code_page_format.py create mode 100644 google/ads/googleads/v15/enums/types/tracking_code_type.py create mode 100644 google/ads/googleads/v15/enums/types/travel_placeholder_field.py create mode 100644 google/ads/googleads/v15/enums/types/user_identifier_source.py create mode 100644 google/ads/googleads/v15/enums/types/user_interest_taxonomy_type.py create mode 100644 google/ads/googleads/v15/enums/types/user_list_access_status.py create mode 100644 google/ads/googleads/v15/enums/types/user_list_closing_reason.py create mode 100644 google/ads/googleads/v15/enums/types/user_list_crm_data_source_type.py create mode 100644 google/ads/googleads/v15/enums/types/user_list_date_rule_item_operator.py create mode 100644 google/ads/googleads/v15/enums/types/user_list_flexible_rule_operator.py create mode 100644 google/ads/googleads/v15/enums/types/user_list_logical_rule_operator.py create mode 100644 google/ads/googleads/v15/enums/types/user_list_membership_status.py create mode 100644 google/ads/googleads/v15/enums/types/user_list_number_rule_item_operator.py create mode 100644 google/ads/googleads/v15/enums/types/user_list_prepopulation_status.py create mode 100644 google/ads/googleads/v15/enums/types/user_list_rule_type.py create mode 100644 google/ads/googleads/v15/enums/types/user_list_size_range.py create mode 100644 google/ads/googleads/v15/enums/types/user_list_string_rule_item_operator.py create mode 100644 google/ads/googleads/v15/enums/types/user_list_type.py create mode 100644 google/ads/googleads/v15/enums/types/value_rule_device_type.py create mode 100644 google/ads/googleads/v15/enums/types/value_rule_geo_location_match_type.py create mode 100644 google/ads/googleads/v15/enums/types/value_rule_operation.py create mode 100644 google/ads/googleads/v15/enums/types/value_rule_set_attachment_type.py create mode 100644 google/ads/googleads/v15/enums/types/value_rule_set_dimension.py create mode 100644 google/ads/googleads/v15/enums/types/vanity_pharma_display_url_mode.py create mode 100644 google/ads/googleads/v15/enums/types/vanity_pharma_text.py create mode 100644 google/ads/googleads/v15/enums/types/video_thumbnail.py create mode 100644 google/ads/googleads/v15/enums/types/webpage_condition_operand.py create mode 100644 google/ads/googleads/v15/enums/types/webpage_condition_operator.py create mode 100644 google/ads/googleads/v15/errors/__init__.py create mode 100644 google/ads/googleads/v15/errors/services/__init__.py create mode 100644 google/ads/googleads/v15/errors/types/__init__.py create mode 100644 google/ads/googleads/v15/errors/types/access_invitation_error.py create mode 100644 google/ads/googleads/v15/errors/types/account_budget_proposal_error.py create mode 100644 google/ads/googleads/v15/errors/types/account_link_error.py create mode 100644 google/ads/googleads/v15/errors/types/ad_customizer_error.py create mode 100644 google/ads/googleads/v15/errors/types/ad_error.py create mode 100644 google/ads/googleads/v15/errors/types/ad_group_ad_error.py create mode 100644 google/ads/googleads/v15/errors/types/ad_group_bid_modifier_error.py create mode 100644 google/ads/googleads/v15/errors/types/ad_group_criterion_customizer_error.py create mode 100644 google/ads/googleads/v15/errors/types/ad_group_criterion_error.py create mode 100644 google/ads/googleads/v15/errors/types/ad_group_customizer_error.py create mode 100644 google/ads/googleads/v15/errors/types/ad_group_error.py create mode 100644 google/ads/googleads/v15/errors/types/ad_group_feed_error.py create mode 100644 google/ads/googleads/v15/errors/types/ad_parameter_error.py create mode 100644 google/ads/googleads/v15/errors/types/ad_sharing_error.py create mode 100644 google/ads/googleads/v15/errors/types/adx_error.py create mode 100644 google/ads/googleads/v15/errors/types/asset_error.py create mode 100644 google/ads/googleads/v15/errors/types/asset_group_asset_error.py create mode 100644 google/ads/googleads/v15/errors/types/asset_group_error.py create mode 100644 google/ads/googleads/v15/errors/types/asset_group_listing_group_filter_error.py create mode 100644 google/ads/googleads/v15/errors/types/asset_group_signal_error.py create mode 100644 google/ads/googleads/v15/errors/types/asset_link_error.py create mode 100644 google/ads/googleads/v15/errors/types/asset_set_asset_error.py create mode 100644 google/ads/googleads/v15/errors/types/asset_set_error.py create mode 100644 google/ads/googleads/v15/errors/types/asset_set_link_error.py create mode 100644 google/ads/googleads/v15/errors/types/audience_error.py create mode 100644 google/ads/googleads/v15/errors/types/audience_insights_error.py create mode 100644 google/ads/googleads/v15/errors/types/authentication_error.py create mode 100644 google/ads/googleads/v15/errors/types/authorization_error.py create mode 100644 google/ads/googleads/v15/errors/types/batch_job_error.py create mode 100644 google/ads/googleads/v15/errors/types/bidding_error.py create mode 100644 google/ads/googleads/v15/errors/types/bidding_strategy_error.py create mode 100644 google/ads/googleads/v15/errors/types/billing_setup_error.py create mode 100644 google/ads/googleads/v15/errors/types/campaign_budget_error.py create mode 100644 google/ads/googleads/v15/errors/types/campaign_conversion_goal_error.py create mode 100644 google/ads/googleads/v15/errors/types/campaign_criterion_error.py create mode 100644 google/ads/googleads/v15/errors/types/campaign_customizer_error.py create mode 100644 google/ads/googleads/v15/errors/types/campaign_draft_error.py create mode 100644 google/ads/googleads/v15/errors/types/campaign_error.py create mode 100644 google/ads/googleads/v15/errors/types/campaign_experiment_error.py create mode 100644 google/ads/googleads/v15/errors/types/campaign_feed_error.py create mode 100644 google/ads/googleads/v15/errors/types/campaign_lifecycle_goal_error.py create mode 100644 google/ads/googleads/v15/errors/types/campaign_shared_set_error.py create mode 100644 google/ads/googleads/v15/errors/types/change_event_error.py create mode 100644 google/ads/googleads/v15/errors/types/change_status_error.py create mode 100644 google/ads/googleads/v15/errors/types/collection_size_error.py create mode 100644 google/ads/googleads/v15/errors/types/context_error.py create mode 100644 google/ads/googleads/v15/errors/types/conversion_action_error.py create mode 100644 google/ads/googleads/v15/errors/types/conversion_adjustment_upload_error.py create mode 100644 google/ads/googleads/v15/errors/types/conversion_custom_variable_error.py create mode 100644 google/ads/googleads/v15/errors/types/conversion_goal_campaign_config_error.py create mode 100644 google/ads/googleads/v15/errors/types/conversion_upload_error.py create mode 100644 google/ads/googleads/v15/errors/types/conversion_value_rule_error.py create mode 100644 google/ads/googleads/v15/errors/types/conversion_value_rule_set_error.py create mode 100644 google/ads/googleads/v15/errors/types/country_code_error.py create mode 100644 google/ads/googleads/v15/errors/types/criterion_error.py create mode 100644 google/ads/googleads/v15/errors/types/currency_code_error.py create mode 100644 google/ads/googleads/v15/errors/types/currency_error.py create mode 100644 google/ads/googleads/v15/errors/types/custom_audience_error.py create mode 100644 google/ads/googleads/v15/errors/types/custom_conversion_goal_error.py create mode 100644 google/ads/googleads/v15/errors/types/custom_interest_error.py create mode 100644 google/ads/googleads/v15/errors/types/customer_client_link_error.py create mode 100644 google/ads/googleads/v15/errors/types/customer_customizer_error.py create mode 100644 google/ads/googleads/v15/errors/types/customer_error.py create mode 100644 google/ads/googleads/v15/errors/types/customer_feed_error.py create mode 100644 google/ads/googleads/v15/errors/types/customer_lifecycle_goal_error.py create mode 100644 google/ads/googleads/v15/errors/types/customer_manager_link_error.py create mode 100644 google/ads/googleads/v15/errors/types/customer_sk_ad_network_conversion_value_schema_error.py create mode 100644 google/ads/googleads/v15/errors/types/customer_user_access_error.py create mode 100644 google/ads/googleads/v15/errors/types/customizer_attribute_error.py create mode 100644 google/ads/googleads/v15/errors/types/database_error.py create mode 100644 google/ads/googleads/v15/errors/types/date_error.py create mode 100644 google/ads/googleads/v15/errors/types/date_range_error.py create mode 100644 google/ads/googleads/v15/errors/types/distinct_error.py create mode 100644 google/ads/googleads/v15/errors/types/enum_error.py create mode 100644 google/ads/googleads/v15/errors/types/errors.py create mode 100644 google/ads/googleads/v15/errors/types/experiment_arm_error.py create mode 100644 google/ads/googleads/v15/errors/types/experiment_error.py create mode 100644 google/ads/googleads/v15/errors/types/extension_feed_item_error.py create mode 100644 google/ads/googleads/v15/errors/types/extension_setting_error.py create mode 100644 google/ads/googleads/v15/errors/types/feed_attribute_reference_error.py create mode 100644 google/ads/googleads/v15/errors/types/feed_error.py create mode 100644 google/ads/googleads/v15/errors/types/feed_item_error.py create mode 100644 google/ads/googleads/v15/errors/types/feed_item_set_error.py create mode 100644 google/ads/googleads/v15/errors/types/feed_item_set_link_error.py create mode 100644 google/ads/googleads/v15/errors/types/feed_item_target_error.py create mode 100644 google/ads/googleads/v15/errors/types/feed_item_validation_error.py create mode 100644 google/ads/googleads/v15/errors/types/feed_mapping_error.py create mode 100644 google/ads/googleads/v15/errors/types/field_error.py create mode 100644 google/ads/googleads/v15/errors/types/field_mask_error.py create mode 100644 google/ads/googleads/v15/errors/types/function_error.py create mode 100644 google/ads/googleads/v15/errors/types/function_parsing_error.py create mode 100644 google/ads/googleads/v15/errors/types/geo_target_constant_suggestion_error.py create mode 100644 google/ads/googleads/v15/errors/types/header_error.py create mode 100644 google/ads/googleads/v15/errors/types/id_error.py create mode 100644 google/ads/googleads/v15/errors/types/image_error.py create mode 100644 google/ads/googleads/v15/errors/types/internal_error.py create mode 100644 google/ads/googleads/v15/errors/types/invoice_error.py create mode 100644 google/ads/googleads/v15/errors/types/keyword_plan_ad_group_error.py create mode 100644 google/ads/googleads/v15/errors/types/keyword_plan_ad_group_keyword_error.py create mode 100644 google/ads/googleads/v15/errors/types/keyword_plan_campaign_error.py create mode 100644 google/ads/googleads/v15/errors/types/keyword_plan_campaign_keyword_error.py create mode 100644 google/ads/googleads/v15/errors/types/keyword_plan_error.py create mode 100644 google/ads/googleads/v15/errors/types/keyword_plan_idea_error.py create mode 100644 google/ads/googleads/v15/errors/types/label_error.py create mode 100644 google/ads/googleads/v15/errors/types/language_code_error.py create mode 100644 google/ads/googleads/v15/errors/types/list_operation_error.py create mode 100644 google/ads/googleads/v15/errors/types/manager_link_error.py create mode 100644 google/ads/googleads/v15/errors/types/media_bundle_error.py create mode 100644 google/ads/googleads/v15/errors/types/media_file_error.py create mode 100644 google/ads/googleads/v15/errors/types/media_upload_error.py create mode 100644 google/ads/googleads/v15/errors/types/merchant_center_error.py create mode 100644 google/ads/googleads/v15/errors/types/multiplier_error.py create mode 100644 google/ads/googleads/v15/errors/types/mutate_error.py create mode 100644 google/ads/googleads/v15/errors/types/new_resource_creation_error.py create mode 100644 google/ads/googleads/v15/errors/types/not_allowlisted_error.py create mode 100644 google/ads/googleads/v15/errors/types/not_empty_error.py create mode 100644 google/ads/googleads/v15/errors/types/null_error.py create mode 100644 google/ads/googleads/v15/errors/types/offline_user_data_job_error.py create mode 100644 google/ads/googleads/v15/errors/types/operation_access_denied_error.py create mode 100644 google/ads/googleads/v15/errors/types/operator_error.py create mode 100644 google/ads/googleads/v15/errors/types/partial_failure_error.py create mode 100644 google/ads/googleads/v15/errors/types/payments_account_error.py create mode 100644 google/ads/googleads/v15/errors/types/policy_finding_error.py create mode 100644 google/ads/googleads/v15/errors/types/policy_validation_parameter_error.py create mode 100644 google/ads/googleads/v15/errors/types/policy_violation_error.py create mode 100644 google/ads/googleads/v15/errors/types/product_link_error.py create mode 100644 google/ads/googleads/v15/errors/types/product_link_invitation_error.py create mode 100644 google/ads/googleads/v15/errors/types/query_error.py create mode 100644 google/ads/googleads/v15/errors/types/quota_error.py create mode 100644 google/ads/googleads/v15/errors/types/range_error.py create mode 100644 google/ads/googleads/v15/errors/types/reach_plan_error.py create mode 100644 google/ads/googleads/v15/errors/types/recommendation_error.py create mode 100644 google/ads/googleads/v15/errors/types/recommendation_subscription_error.py create mode 100644 google/ads/googleads/v15/errors/types/region_code_error.py create mode 100644 google/ads/googleads/v15/errors/types/request_error.py create mode 100644 google/ads/googleads/v15/errors/types/resource_access_denied_error.py create mode 100644 google/ads/googleads/v15/errors/types/resource_count_limit_exceeded_error.py create mode 100644 google/ads/googleads/v15/errors/types/search_term_insight_error.py create mode 100644 google/ads/googleads/v15/errors/types/setting_error.py create mode 100644 google/ads/googleads/v15/errors/types/shared_criterion_error.py create mode 100644 google/ads/googleads/v15/errors/types/shared_set_error.py create mode 100644 google/ads/googleads/v15/errors/types/size_limit_error.py create mode 100644 google/ads/googleads/v15/errors/types/smart_campaign_error.py create mode 100644 google/ads/googleads/v15/errors/types/string_format_error.py create mode 100644 google/ads/googleads/v15/errors/types/string_length_error.py create mode 100644 google/ads/googleads/v15/errors/types/third_party_app_analytics_link_error.py create mode 100644 google/ads/googleads/v15/errors/types/time_zone_error.py create mode 100644 google/ads/googleads/v15/errors/types/url_field_error.py create mode 100644 google/ads/googleads/v15/errors/types/user_data_error.py create mode 100644 google/ads/googleads/v15/errors/types/user_list_error.py create mode 100644 google/ads/googleads/v15/errors/types/youtube_video_registration_error.py create mode 100644 google/ads/googleads/v15/resources/__init__.py create mode 100644 google/ads/googleads/v15/resources/services/__init__.py create mode 100644 google/ads/googleads/v15/resources/types/__init__.py create mode 100644 google/ads/googleads/v15/resources/types/accessible_bidding_strategy.py create mode 100644 google/ads/googleads/v15/resources/types/account_budget.py create mode 100644 google/ads/googleads/v15/resources/types/account_budget_proposal.py create mode 100644 google/ads/googleads/v15/resources/types/account_link.py create mode 100644 google/ads/googleads/v15/resources/types/ad.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_ad.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_ad_asset_combination_view.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_ad_asset_view.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_ad_label.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_asset.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_asset_set.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_audience_view.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_bid_modifier.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_criterion.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_criterion_customizer.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_criterion_label.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_criterion_simulation.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_customizer.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_extension_setting.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_feed.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_label.py create mode 100644 google/ads/googleads/v15/resources/types/ad_group_simulation.py create mode 100644 google/ads/googleads/v15/resources/types/ad_parameter.py create mode 100644 google/ads/googleads/v15/resources/types/ad_schedule_view.py create mode 100644 google/ads/googleads/v15/resources/types/age_range_view.py create mode 100644 google/ads/googleads/v15/resources/types/android_privacy_shared_key_google_ad_group.py create mode 100644 google/ads/googleads/v15/resources/types/android_privacy_shared_key_google_campaign.py create mode 100644 google/ads/googleads/v15/resources/types/android_privacy_shared_key_google_network_type.py create mode 100644 google/ads/googleads/v15/resources/types/asset.py create mode 100644 google/ads/googleads/v15/resources/types/asset_field_type_view.py create mode 100644 google/ads/googleads/v15/resources/types/asset_group.py create mode 100644 google/ads/googleads/v15/resources/types/asset_group_asset.py create mode 100644 google/ads/googleads/v15/resources/types/asset_group_listing_group_filter.py create mode 100644 google/ads/googleads/v15/resources/types/asset_group_product_group_view.py create mode 100644 google/ads/googleads/v15/resources/types/asset_group_signal.py create mode 100644 google/ads/googleads/v15/resources/types/asset_group_top_combination_view.py create mode 100644 google/ads/googleads/v15/resources/types/asset_set.py create mode 100644 google/ads/googleads/v15/resources/types/asset_set_asset.py create mode 100644 google/ads/googleads/v15/resources/types/asset_set_type_view.py create mode 100644 google/ads/googleads/v15/resources/types/audience.py create mode 100644 google/ads/googleads/v15/resources/types/batch_job.py create mode 100644 google/ads/googleads/v15/resources/types/bidding_data_exclusion.py create mode 100644 google/ads/googleads/v15/resources/types/bidding_seasonality_adjustment.py create mode 100644 google/ads/googleads/v15/resources/types/bidding_strategy.py create mode 100644 google/ads/googleads/v15/resources/types/bidding_strategy_simulation.py create mode 100644 google/ads/googleads/v15/resources/types/billing_setup.py create mode 100644 google/ads/googleads/v15/resources/types/call_view.py create mode 100644 google/ads/googleads/v15/resources/types/campaign.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_asset.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_asset_set.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_audience_view.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_bid_modifier.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_budget.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_conversion_goal.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_criterion.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_customizer.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_draft.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_extension_setting.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_feed.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_group.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_label.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_lifecycle_goal.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_search_term_insight.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_shared_set.py create mode 100644 google/ads/googleads/v15/resources/types/campaign_simulation.py create mode 100644 google/ads/googleads/v15/resources/types/carrier_constant.py create mode 100644 google/ads/googleads/v15/resources/types/change_event.py create mode 100644 google/ads/googleads/v15/resources/types/change_status.py create mode 100644 google/ads/googleads/v15/resources/types/click_view.py create mode 100644 google/ads/googleads/v15/resources/types/combined_audience.py create mode 100644 google/ads/googleads/v15/resources/types/conversion_action.py create mode 100644 google/ads/googleads/v15/resources/types/conversion_custom_variable.py create mode 100644 google/ads/googleads/v15/resources/types/conversion_goal_campaign_config.py create mode 100644 google/ads/googleads/v15/resources/types/conversion_value_rule.py create mode 100644 google/ads/googleads/v15/resources/types/conversion_value_rule_set.py create mode 100644 google/ads/googleads/v15/resources/types/currency_constant.py create mode 100644 google/ads/googleads/v15/resources/types/custom_audience.py create mode 100644 google/ads/googleads/v15/resources/types/custom_conversion_goal.py create mode 100644 google/ads/googleads/v15/resources/types/custom_interest.py create mode 100644 google/ads/googleads/v15/resources/types/customer.py create mode 100644 google/ads/googleads/v15/resources/types/customer_asset.py create mode 100644 google/ads/googleads/v15/resources/types/customer_asset_set.py create mode 100644 google/ads/googleads/v15/resources/types/customer_client.py create mode 100644 google/ads/googleads/v15/resources/types/customer_client_link.py create mode 100644 google/ads/googleads/v15/resources/types/customer_conversion_goal.py create mode 100644 google/ads/googleads/v15/resources/types/customer_customizer.py create mode 100644 google/ads/googleads/v15/resources/types/customer_extension_setting.py create mode 100644 google/ads/googleads/v15/resources/types/customer_feed.py create mode 100644 google/ads/googleads/v15/resources/types/customer_label.py create mode 100644 google/ads/googleads/v15/resources/types/customer_lifecycle_goal.py create mode 100644 google/ads/googleads/v15/resources/types/customer_manager_link.py create mode 100644 google/ads/googleads/v15/resources/types/customer_negative_criterion.py create mode 100644 google/ads/googleads/v15/resources/types/customer_search_term_insight.py create mode 100644 google/ads/googleads/v15/resources/types/customer_sk_ad_network_conversion_value_schema.py create mode 100644 google/ads/googleads/v15/resources/types/customer_user_access.py create mode 100644 google/ads/googleads/v15/resources/types/customer_user_access_invitation.py create mode 100644 google/ads/googleads/v15/resources/types/customizer_attribute.py create mode 100644 google/ads/googleads/v15/resources/types/detail_placement_view.py create mode 100644 google/ads/googleads/v15/resources/types/detailed_demographic.py create mode 100644 google/ads/googleads/v15/resources/types/display_keyword_view.py create mode 100644 google/ads/googleads/v15/resources/types/distance_view.py create mode 100644 google/ads/googleads/v15/resources/types/domain_category.py create mode 100644 google/ads/googleads/v15/resources/types/dynamic_search_ads_search_term_view.py create mode 100644 google/ads/googleads/v15/resources/types/expanded_landing_page_view.py create mode 100644 google/ads/googleads/v15/resources/types/experiment.py create mode 100644 google/ads/googleads/v15/resources/types/experiment_arm.py create mode 100644 google/ads/googleads/v15/resources/types/extension_feed_item.py create mode 100644 google/ads/googleads/v15/resources/types/feed.py create mode 100644 google/ads/googleads/v15/resources/types/feed_item.py create mode 100644 google/ads/googleads/v15/resources/types/feed_item_set.py create mode 100644 google/ads/googleads/v15/resources/types/feed_item_set_link.py create mode 100644 google/ads/googleads/v15/resources/types/feed_item_target.py create mode 100644 google/ads/googleads/v15/resources/types/feed_mapping.py create mode 100644 google/ads/googleads/v15/resources/types/feed_placeholder_view.py create mode 100644 google/ads/googleads/v15/resources/types/gender_view.py create mode 100644 google/ads/googleads/v15/resources/types/geo_target_constant.py create mode 100644 google/ads/googleads/v15/resources/types/geographic_view.py create mode 100644 google/ads/googleads/v15/resources/types/google_ads_field.py create mode 100644 google/ads/googleads/v15/resources/types/group_placement_view.py create mode 100644 google/ads/googleads/v15/resources/types/hotel_group_view.py create mode 100644 google/ads/googleads/v15/resources/types/hotel_performance_view.py create mode 100644 google/ads/googleads/v15/resources/types/hotel_reconciliation.py create mode 100644 google/ads/googleads/v15/resources/types/income_range_view.py create mode 100644 google/ads/googleads/v15/resources/types/invoice.py create mode 100644 google/ads/googleads/v15/resources/types/keyword_plan.py create mode 100644 google/ads/googleads/v15/resources/types/keyword_plan_ad_group.py create mode 100644 google/ads/googleads/v15/resources/types/keyword_plan_ad_group_keyword.py create mode 100644 google/ads/googleads/v15/resources/types/keyword_plan_campaign.py create mode 100644 google/ads/googleads/v15/resources/types/keyword_plan_campaign_keyword.py create mode 100644 google/ads/googleads/v15/resources/types/keyword_theme_constant.py create mode 100644 google/ads/googleads/v15/resources/types/keyword_view.py create mode 100644 google/ads/googleads/v15/resources/types/label.py create mode 100644 google/ads/googleads/v15/resources/types/landing_page_view.py create mode 100644 google/ads/googleads/v15/resources/types/language_constant.py create mode 100644 google/ads/googleads/v15/resources/types/lead_form_submission_data.py create mode 100644 google/ads/googleads/v15/resources/types/life_event.py create mode 100644 google/ads/googleads/v15/resources/types/local_services_lead.py create mode 100644 google/ads/googleads/v15/resources/types/local_services_lead_conversation.py create mode 100644 google/ads/googleads/v15/resources/types/local_services_verification_artifact.py create mode 100644 google/ads/googleads/v15/resources/types/location_view.py create mode 100644 google/ads/googleads/v15/resources/types/managed_placement_view.py create mode 100644 google/ads/googleads/v15/resources/types/media_file.py create mode 100644 google/ads/googleads/v15/resources/types/mobile_app_category_constant.py create mode 100644 google/ads/googleads/v15/resources/types/mobile_device_constant.py create mode 100644 google/ads/googleads/v15/resources/types/offline_conversion_upload_client_summary.py create mode 100644 google/ads/googleads/v15/resources/types/offline_user_data_job.py create mode 100644 google/ads/googleads/v15/resources/types/operating_system_version_constant.py create mode 100644 google/ads/googleads/v15/resources/types/paid_organic_search_term_view.py create mode 100644 google/ads/googleads/v15/resources/types/parental_status_view.py create mode 100644 google/ads/googleads/v15/resources/types/payments_account.py create mode 100644 google/ads/googleads/v15/resources/types/per_store_view.py create mode 100644 google/ads/googleads/v15/resources/types/product_category_constant.py create mode 100644 google/ads/googleads/v15/resources/types/product_group_view.py create mode 100644 google/ads/googleads/v15/resources/types/product_link.py create mode 100644 google/ads/googleads/v15/resources/types/product_link_invitation.py create mode 100644 google/ads/googleads/v15/resources/types/qualifying_question.py create mode 100644 google/ads/googleads/v15/resources/types/recommendation.py create mode 100644 google/ads/googleads/v15/resources/types/recommendation_subscription.py create mode 100644 google/ads/googleads/v15/resources/types/remarketing_action.py create mode 100644 google/ads/googleads/v15/resources/types/search_term_view.py create mode 100644 google/ads/googleads/v15/resources/types/shared_criterion.py create mode 100644 google/ads/googleads/v15/resources/types/shared_set.py create mode 100644 google/ads/googleads/v15/resources/types/shopping_performance_view.py create mode 100644 google/ads/googleads/v15/resources/types/smart_campaign_search_term_view.py create mode 100644 google/ads/googleads/v15/resources/types/smart_campaign_setting.py create mode 100644 google/ads/googleads/v15/resources/types/third_party_app_analytics_link.py create mode 100644 google/ads/googleads/v15/resources/types/topic_constant.py create mode 100644 google/ads/googleads/v15/resources/types/topic_view.py create mode 100644 google/ads/googleads/v15/resources/types/travel_activity_group_view.py create mode 100644 google/ads/googleads/v15/resources/types/travel_activity_performance_view.py create mode 100644 google/ads/googleads/v15/resources/types/user_interest.py create mode 100644 google/ads/googleads/v15/resources/types/user_list.py create mode 100644 google/ads/googleads/v15/resources/types/user_location_view.py create mode 100644 google/ads/googleads/v15/resources/types/video.py create mode 100644 google/ads/googleads/v15/resources/types/webpage_view.py create mode 100644 google/ads/googleads/v15/services/__init__.py create mode 100644 google/ads/googleads/v15/services/services/__init__.py create mode 100644 google/ads/googleads/v15/services/services/account_budget_proposal_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/account_budget_proposal_service/client.py create mode 100644 google/ads/googleads/v15/services/services/account_budget_proposal_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/account_budget_proposal_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/account_budget_proposal_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/account_link_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/account_link_service/client.py create mode 100644 google/ads/googleads/v15/services/services/account_link_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/account_link_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/account_link_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_ad_label_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_ad_label_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_ad_label_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_ad_label_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_ad_label_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_ad_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_ad_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_ad_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_ad_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_ad_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_asset_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_asset_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_asset_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_asset_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_asset_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_asset_set_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_asset_set_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_asset_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_asset_set_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_asset_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_label_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_label_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_label_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_label_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_label_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_criterion_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_customizer_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_customizer_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_customizer_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_customizer_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_customizer_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_extension_setting_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_extension_setting_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_extension_setting_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_extension_setting_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_extension_setting_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_feed_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_feed_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_feed_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_feed_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_feed_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_label_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_label_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_label_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_label_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_label_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_group_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_parameter_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_parameter_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_parameter_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_parameter_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_parameter_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/ad_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_service/client.py create mode 100644 google/ads/googleads/v15/services/services/ad_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/ad_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/ad_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_asset_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_asset_service/client.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_asset_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_asset_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_asset_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/client.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_service/client.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_signal_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_signal_service/client.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_signal_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_signal_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/asset_group_signal_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/asset_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_service/client.py create mode 100644 google/ads/googleads/v15/services/services/asset_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/asset_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/asset_set_asset_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_set_asset_service/client.py create mode 100644 google/ads/googleads/v15/services/services/asset_set_asset_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_set_asset_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/asset_set_asset_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/asset_set_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_set_service/client.py create mode 100644 google/ads/googleads/v15/services/services/asset_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/asset_set_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/asset_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/audience_insights_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/audience_insights_service/client.py create mode 100644 google/ads/googleads/v15/services/services/audience_insights_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/audience_insights_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/audience_insights_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/audience_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/audience_service/client.py create mode 100644 google/ads/googleads/v15/services/services/audience_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/audience_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/audience_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/batch_job_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/batch_job_service/client.py create mode 100644 google/ads/googleads/v15/services/services/batch_job_service/pagers.py create mode 100644 google/ads/googleads/v15/services/services/batch_job_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/batch_job_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/batch_job_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/bidding_data_exclusion_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/bidding_data_exclusion_service/client.py create mode 100644 google/ads/googleads/v15/services/services/bidding_data_exclusion_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/bidding_data_exclusion_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/bidding_data_exclusion_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/client.py create mode 100644 google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/bidding_strategy_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/bidding_strategy_service/client.py create mode 100644 google/ads/googleads/v15/services/services/bidding_strategy_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/bidding_strategy_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/bidding_strategy_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/billing_setup_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/billing_setup_service/client.py create mode 100644 google/ads/googleads/v15/services/services/billing_setup_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/billing_setup_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/billing_setup_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/brand_suggestion_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/brand_suggestion_service/client.py create mode 100644 google/ads/googleads/v15/services/services/brand_suggestion_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/brand_suggestion_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/brand_suggestion_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_asset_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_asset_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_asset_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_asset_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_asset_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_asset_set_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_asset_set_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_asset_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_asset_set_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_asset_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_bid_modifier_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_bid_modifier_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_bid_modifier_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_bid_modifier_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_bid_modifier_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_budget_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_budget_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_budget_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_budget_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_budget_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_conversion_goal_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_conversion_goal_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_conversion_goal_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_conversion_goal_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_conversion_goal_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_criterion_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_criterion_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_criterion_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_criterion_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_criterion_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_customizer_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_customizer_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_customizer_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_customizer_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_customizer_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_draft_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_draft_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_draft_service/pagers.py create mode 100644 google/ads/googleads/v15/services/services/campaign_draft_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_draft_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_draft_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_extension_setting_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_extension_setting_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_extension_setting_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_extension_setting_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_extension_setting_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_feed_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_feed_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_feed_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_feed_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_feed_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_group_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_group_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_group_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_group_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_group_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_label_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_label_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_label_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_label_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_label_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/campaign_shared_set_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_shared_set_service/client.py create mode 100644 google/ads/googleads/v15/services/services/campaign_shared_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/campaign_shared_set_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/campaign_shared_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/conversion_action_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_action_service/client.py create mode 100644 google/ads/googleads/v15/services/services/conversion_action_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_action_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/conversion_action_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/client.py create mode 100644 google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/conversion_custom_variable_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_custom_variable_service/client.py create mode 100644 google/ads/googleads/v15/services/services/conversion_custom_variable_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_custom_variable_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/conversion_custom_variable_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/client.py create mode 100644 google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/conversion_upload_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_upload_service/client.py create mode 100644 google/ads/googleads/v15/services/services/conversion_upload_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_upload_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/conversion_upload_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/conversion_value_rule_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_value_rule_service/client.py create mode 100644 google/ads/googleads/v15/services/services/conversion_value_rule_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_value_rule_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/conversion_value_rule_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/conversion_value_rule_set_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_value_rule_set_service/client.py create mode 100644 google/ads/googleads/v15/services/services/conversion_value_rule_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/conversion_value_rule_set_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/conversion_value_rule_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/custom_audience_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/custom_audience_service/client.py create mode 100644 google/ads/googleads/v15/services/services/custom_audience_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/custom_audience_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/custom_audience_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/custom_conversion_goal_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/custom_conversion_goal_service/client.py create mode 100644 google/ads/googleads/v15/services/services/custom_conversion_goal_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/custom_conversion_goal_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/custom_conversion_goal_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/custom_interest_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/custom_interest_service/client.py create mode 100644 google/ads/googleads/v15/services/services/custom_interest_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/custom_interest_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/custom_interest_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_asset_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_asset_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_asset_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_asset_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_asset_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_asset_set_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_asset_set_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_asset_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_asset_set_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_asset_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_client_link_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_client_link_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_client_link_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_client_link_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_client_link_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_conversion_goal_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_conversion_goal_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_conversion_goal_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_conversion_goal_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_conversion_goal_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_customizer_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_customizer_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_customizer_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_customizer_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_customizer_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_extension_setting_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_extension_setting_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_extension_setting_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_extension_setting_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_extension_setting_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_feed_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_feed_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_feed_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_feed_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_feed_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_label_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_label_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_label_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_label_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_label_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_manager_link_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_manager_link_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_manager_link_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_manager_link_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_manager_link_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_negative_criterion_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_negative_criterion_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_negative_criterion_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_negative_criterion_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_negative_criterion_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_user_access_invitation_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_user_access_invitation_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_user_access_invitation_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_user_access_invitation_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_user_access_invitation_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customer_user_access_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_user_access_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customer_user_access_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customer_user_access_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customer_user_access_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/customizer_attribute_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customizer_attribute_service/client.py create mode 100644 google/ads/googleads/v15/services/services/customizer_attribute_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/customizer_attribute_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/customizer_attribute_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/experiment_arm_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/experiment_arm_service/client.py create mode 100644 google/ads/googleads/v15/services/services/experiment_arm_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/experiment_arm_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/experiment_arm_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/experiment_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/experiment_service/client.py create mode 100644 google/ads/googleads/v15/services/services/experiment_service/pagers.py create mode 100644 google/ads/googleads/v15/services/services/experiment_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/experiment_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/experiment_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/extension_feed_item_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/extension_feed_item_service/client.py create mode 100644 google/ads/googleads/v15/services/services/extension_feed_item_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/extension_feed_item_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/extension_feed_item_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_service/client.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_set_link_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_set_link_service/client.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_set_link_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_set_link_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_set_link_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_set_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_set_service/client.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_set_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_target_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_target_service/client.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_target_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_target_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/feed_item_target_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/feed_mapping_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/feed_mapping_service/client.py create mode 100644 google/ads/googleads/v15/services/services/feed_mapping_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/feed_mapping_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/feed_mapping_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/feed_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/feed_service/client.py create mode 100644 google/ads/googleads/v15/services/services/feed_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/feed_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/feed_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/geo_target_constant_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/geo_target_constant_service/client.py create mode 100644 google/ads/googleads/v15/services/services/geo_target_constant_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/geo_target_constant_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/geo_target_constant_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/google_ads_field_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/google_ads_field_service/client.py create mode 100644 google/ads/googleads/v15/services/services/google_ads_field_service/pagers.py create mode 100644 google/ads/googleads/v15/services/services/google_ads_field_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/google_ads_field_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/google_ads_field_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/google_ads_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/google_ads_service/client.py create mode 100644 google/ads/googleads/v15/services/services/google_ads_service/pagers.py create mode 100644 google/ads/googleads/v15/services/services/google_ads_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/google_ads_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/google_ads_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/invoice_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/invoice_service/client.py create mode 100644 google/ads/googleads/v15/services/services/invoice_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/invoice_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/invoice_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/client.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/client.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/client.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_campaign_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_campaign_service/client.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_campaign_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_campaign_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_campaign_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_idea_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_idea_service/client.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_idea_service/pagers.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_idea_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_idea_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_idea_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_service/client.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/keyword_plan_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/keyword_theme_constant_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_theme_constant_service/client.py create mode 100644 google/ads/googleads/v15/services/services/keyword_theme_constant_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/keyword_theme_constant_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/keyword_theme_constant_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/label_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/label_service/client.py create mode 100644 google/ads/googleads/v15/services/services/label_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/label_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/label_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/offline_user_data_job_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/offline_user_data_job_service/client.py create mode 100644 google/ads/googleads/v15/services/services/offline_user_data_job_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/offline_user_data_job_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/offline_user_data_job_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/payments_account_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/payments_account_service/client.py create mode 100644 google/ads/googleads/v15/services/services/payments_account_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/payments_account_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/payments_account_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/product_link_invitation_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/product_link_invitation_service/client.py create mode 100644 google/ads/googleads/v15/services/services/product_link_invitation_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/product_link_invitation_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/product_link_invitation_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/product_link_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/product_link_service/client.py create mode 100644 google/ads/googleads/v15/services/services/product_link_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/product_link_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/product_link_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/reach_plan_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/reach_plan_service/client.py create mode 100644 google/ads/googleads/v15/services/services/reach_plan_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/reach_plan_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/reach_plan_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/recommendation_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/recommendation_service/client.py create mode 100644 google/ads/googleads/v15/services/services/recommendation_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/recommendation_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/recommendation_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/recommendation_subscription_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/recommendation_subscription_service/client.py create mode 100644 google/ads/googleads/v15/services/services/recommendation_subscription_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/recommendation_subscription_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/recommendation_subscription_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/remarketing_action_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/remarketing_action_service/client.py create mode 100644 google/ads/googleads/v15/services/services/remarketing_action_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/remarketing_action_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/remarketing_action_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/shared_criterion_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/shared_criterion_service/client.py create mode 100644 google/ads/googleads/v15/services/services/shared_criterion_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/shared_criterion_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/shared_criterion_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/shared_set_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/shared_set_service/client.py create mode 100644 google/ads/googleads/v15/services/services/shared_set_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/shared_set_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/shared_set_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/smart_campaign_setting_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/smart_campaign_setting_service/client.py create mode 100644 google/ads/googleads/v15/services/services/smart_campaign_setting_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/smart_campaign_setting_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/smart_campaign_setting_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/smart_campaign_suggest_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/smart_campaign_suggest_service/client.py create mode 100644 google/ads/googleads/v15/services/services/smart_campaign_suggest_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/smart_campaign_suggest_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/smart_campaign_suggest_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/client.py create mode 100644 google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/travel_asset_suggestion_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/travel_asset_suggestion_service/client.py create mode 100644 google/ads/googleads/v15/services/services/travel_asset_suggestion_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/travel_asset_suggestion_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/travel_asset_suggestion_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/user_data_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/user_data_service/client.py create mode 100644 google/ads/googleads/v15/services/services/user_data_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/user_data_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/user_data_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/services/user_list_service/__init__.py create mode 100644 google/ads/googleads/v15/services/services/user_list_service/client.py create mode 100644 google/ads/googleads/v15/services/services/user_list_service/transports/__init__.py create mode 100644 google/ads/googleads/v15/services/services/user_list_service/transports/base.py create mode 100644 google/ads/googleads/v15/services/services/user_list_service/transports/grpc.py create mode 100644 google/ads/googleads/v15/services/types/__init__.py create mode 100644 google/ads/googleads/v15/services/types/account_budget_proposal_service.py create mode 100644 google/ads/googleads/v15/services/types/account_link_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_group_ad_label_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_group_ad_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_group_asset_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_group_asset_set_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_group_bid_modifier_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_group_criterion_customizer_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_group_criterion_label_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_group_criterion_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_group_customizer_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_group_extension_setting_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_group_feed_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_group_label_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_group_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_parameter_service.py create mode 100644 google/ads/googleads/v15/services/types/ad_service.py create mode 100644 google/ads/googleads/v15/services/types/asset_group_asset_service.py create mode 100644 google/ads/googleads/v15/services/types/asset_group_listing_group_filter_service.py create mode 100644 google/ads/googleads/v15/services/types/asset_group_service.py create mode 100644 google/ads/googleads/v15/services/types/asset_group_signal_service.py create mode 100644 google/ads/googleads/v15/services/types/asset_service.py create mode 100644 google/ads/googleads/v15/services/types/asset_set_asset_service.py create mode 100644 google/ads/googleads/v15/services/types/asset_set_service.py create mode 100644 google/ads/googleads/v15/services/types/audience_insights_service.py create mode 100644 google/ads/googleads/v15/services/types/audience_service.py create mode 100644 google/ads/googleads/v15/services/types/batch_job_service.py create mode 100644 google/ads/googleads/v15/services/types/bidding_data_exclusion_service.py create mode 100644 google/ads/googleads/v15/services/types/bidding_seasonality_adjustment_service.py create mode 100644 google/ads/googleads/v15/services/types/bidding_strategy_service.py create mode 100644 google/ads/googleads/v15/services/types/billing_setup_service.py create mode 100644 google/ads/googleads/v15/services/types/brand_suggestion_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_asset_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_asset_set_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_bid_modifier_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_budget_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_conversion_goal_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_criterion_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_customizer_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_draft_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_extension_setting_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_feed_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_group_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_label_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_lifecycle_goal_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_service.py create mode 100644 google/ads/googleads/v15/services/types/campaign_shared_set_service.py create mode 100644 google/ads/googleads/v15/services/types/conversion_action_service.py create mode 100644 google/ads/googleads/v15/services/types/conversion_adjustment_upload_service.py create mode 100644 google/ads/googleads/v15/services/types/conversion_custom_variable_service.py create mode 100644 google/ads/googleads/v15/services/types/conversion_goal_campaign_config_service.py create mode 100644 google/ads/googleads/v15/services/types/conversion_upload_service.py create mode 100644 google/ads/googleads/v15/services/types/conversion_value_rule_service.py create mode 100644 google/ads/googleads/v15/services/types/conversion_value_rule_set_service.py create mode 100644 google/ads/googleads/v15/services/types/custom_audience_service.py create mode 100644 google/ads/googleads/v15/services/types/custom_conversion_goal_service.py create mode 100644 google/ads/googleads/v15/services/types/custom_interest_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_asset_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_asset_set_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_client_link_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_conversion_goal_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_customizer_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_extension_setting_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_feed_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_label_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_lifecycle_goal_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_manager_link_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_negative_criterion_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_sk_ad_network_conversion_value_schema_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_user_access_invitation_service.py create mode 100644 google/ads/googleads/v15/services/types/customer_user_access_service.py create mode 100644 google/ads/googleads/v15/services/types/customizer_attribute_service.py create mode 100644 google/ads/googleads/v15/services/types/experiment_arm_service.py create mode 100644 google/ads/googleads/v15/services/types/experiment_service.py create mode 100644 google/ads/googleads/v15/services/types/extension_feed_item_service.py create mode 100644 google/ads/googleads/v15/services/types/feed_item_service.py create mode 100644 google/ads/googleads/v15/services/types/feed_item_set_link_service.py create mode 100644 google/ads/googleads/v15/services/types/feed_item_set_service.py create mode 100644 google/ads/googleads/v15/services/types/feed_item_target_service.py create mode 100644 google/ads/googleads/v15/services/types/feed_mapping_service.py create mode 100644 google/ads/googleads/v15/services/types/feed_service.py create mode 100644 google/ads/googleads/v15/services/types/geo_target_constant_service.py create mode 100644 google/ads/googleads/v15/services/types/google_ads_field_service.py create mode 100644 google/ads/googleads/v15/services/types/google_ads_service.py create mode 100644 google/ads/googleads/v15/services/types/invoice_service.py create mode 100644 google/ads/googleads/v15/services/types/keyword_plan_ad_group_keyword_service.py create mode 100644 google/ads/googleads/v15/services/types/keyword_plan_ad_group_service.py create mode 100644 google/ads/googleads/v15/services/types/keyword_plan_campaign_keyword_service.py create mode 100644 google/ads/googleads/v15/services/types/keyword_plan_campaign_service.py create mode 100644 google/ads/googleads/v15/services/types/keyword_plan_idea_service.py create mode 100644 google/ads/googleads/v15/services/types/keyword_plan_service.py create mode 100644 google/ads/googleads/v15/services/types/keyword_theme_constant_service.py create mode 100644 google/ads/googleads/v15/services/types/label_service.py create mode 100644 google/ads/googleads/v15/services/types/offline_user_data_job_service.py create mode 100644 google/ads/googleads/v15/services/types/payments_account_service.py create mode 100644 google/ads/googleads/v15/services/types/product_link_invitation_service.py create mode 100644 google/ads/googleads/v15/services/types/product_link_service.py create mode 100644 google/ads/googleads/v15/services/types/reach_plan_service.py create mode 100644 google/ads/googleads/v15/services/types/recommendation_service.py create mode 100644 google/ads/googleads/v15/services/types/recommendation_subscription_service.py create mode 100644 google/ads/googleads/v15/services/types/remarketing_action_service.py create mode 100644 google/ads/googleads/v15/services/types/shared_criterion_service.py create mode 100644 google/ads/googleads/v15/services/types/shared_set_service.py create mode 100644 google/ads/googleads/v15/services/types/smart_campaign_setting_service.py create mode 100644 google/ads/googleads/v15/services/types/smart_campaign_suggest_service.py create mode 100644 google/ads/googleads/v15/services/types/third_party_app_analytics_link_service.py create mode 100644 google/ads/googleads/v15/services/types/travel_asset_suggestion_service.py create mode 100644 google/ads/googleads/v15/services/types/user_data_service.py create mode 100644 google/ads/googleads/v15/services/types/user_list_service.py create mode 100644 google/ads/googleads/v15/types/__init__.py diff --git a/ChangeLog b/ChangeLog index 6c729f412..ae6ff4840 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +* 22.1.0 +- Google Ads API v15 release. +- Add configuration option allowing developer token to be ignored. +- Make "impersonation_email" an optional configuration for service accounts. +- Redact PII fields from new LocalServicesLead and LocalServicesLeadConversation in logs. +- Add DMA consent to conversions and Customer Match examples. +- Update enhanced conversions examples to fit with for-leads and for-web workflows. +- Update usage of ProductBiddingCategoryConstant to ProductCategoryConstant in examples. + * 22.0.0 - Remove support for Google Ads API v12. diff --git a/examples/account_management/approve_merchant_center_link.py b/examples/account_management/approve_merchant_center_link.py index 6fac18e99..d2c04f509 100644 --- a/examples/account_management/approve_merchant_center_link.py +++ b/examples/account_management/approve_merchant_center_link.py @@ -21,6 +21,11 @@ To run this code example, you must use the Merchant Center UI or the Content API for Shopping to send a link request between your Merchant Center and Google Ads accounts. + +NOTE: This code example uses version v14 of the Google Ads API. Version v15 of +the Google Ads API replaces MerchantCenterLinkService with +ProductLinkInvitationService and ProductLinkService. We will add new code +examples using these services shortly. """ import argparse diff --git a/examples/account_management/create_customer.py b/examples/account_management/create_customer.py index 6a8c4df91..0924e5ec8 100755 --- a/examples/account_management/create_customer.py +++ b/examples/account_management/create_customer.py @@ -58,7 +58,7 @@ def main(client, manager_customer_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Creates a new client under the given manager.") diff --git a/examples/account_management/get_account_hierarchy.py b/examples/account_management/get_account_hierarchy.py index 4a3d732dc..4a6c165e8 100755 --- a/examples/account_management/get_account_hierarchy.py +++ b/examples/account_management/get_account_hierarchy.py @@ -179,7 +179,7 @@ def print_account_hierarchy( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="This example gets the account hierarchy of the specified " diff --git a/examples/account_management/get_change_details.py b/examples/account_management/get_change_details.py index ae5668362..d51385282 100755 --- a/examples/account_management/get_change_details.py +++ b/examples/account_management/get_change_details.py @@ -186,7 +186,7 @@ def main(client, customer_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="This example gets specific details about the most recent " diff --git a/examples/account_management/get_change_summary.py b/examples/account_management/get_change_summary.py index c902804ff..3f4843ae2 100755 --- a/examples/account_management/get_change_summary.py +++ b/examples/account_management/get_change_summary.py @@ -85,7 +85,7 @@ def main(client, customer_id): if __name__ == "__main__": # GoogleAdsClient will read a google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/account_management/invite_user_with_access_role.py b/examples/account_management/invite_user_with_access_role.py index e41f59717..ea60c21ab 100755 --- a/examples/account_management/invite_user_with_access_role.py +++ b/examples/account_management/invite_user_with_access_role.py @@ -59,7 +59,7 @@ def main(client, customer_id, email_address, access_role): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/account_management/link_manager_to_client.py b/examples/account_management/link_manager_to_client.py index 087f92be1..bafa93209 100755 --- a/examples/account_management/link_manager_to_client.py +++ b/examples/account_management/link_manager_to_client.py @@ -85,8 +85,12 @@ def main(client, customer_id, manager_customer_id): ) manager_link_operation = client.get_type("CustomerManagerLinkOperation") manager_link = manager_link_operation.update - manager_link.resource_name = customer_manager_link_service.customer_manager_link_path( - customer_id, manager_customer_id, manager_link_id, + manager_link.resource_name = ( + customer_manager_link_service.customer_manager_link_path( + customer_id, + manager_customer_id, + manager_link_id, + ) ) manager_link.status = client.enums.ManagerLinkStatusEnum.ACTIVE @@ -108,7 +112,7 @@ def main(client, customer_id, manager_customer_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/account_management/list_accessible_customers.py b/examples/account_management/list_accessible_customers.py index e80b111b7..ac3f48301 100755 --- a/examples/account_management/list_accessible_customers.py +++ b/examples/account_management/list_accessible_customers.py @@ -44,7 +44,7 @@ def main(client): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") try: main(googleads_client) diff --git a/examples/account_management/reject_merchant_center_link.py b/examples/account_management/reject_merchant_center_link.py index 9935b47d7..3e9ba5ebc 100644 --- a/examples/account_management/reject_merchant_center_link.py +++ b/examples/account_management/reject_merchant_center_link.py @@ -22,6 +22,11 @@ Shopping to send a link request between your Merchant Center and Google Ads accounts. You can find detailed instructions to link your Merchant Center and Google Ads accounts here: https://support.google.com/merchants/answer/6159060. + +NOTE: This code example uses version v14 of the Google Ads API. Version v15 of +the Google Ads API replaces MerchantCenterLinkService with +ProductLinkInvitationService and ProductLinkService. We will add new code +examples using these services shortly. """ import argparse @@ -45,8 +50,10 @@ def main(client, customer_id, merchant_center_account_id): "MerchantCenterLinkService" ) # Get the extant customer account to Merchant Center account links. - list_merchant_center_links_response = merchant_center_link_service.list_merchant_center_links( - customer_id=customer_id + list_merchant_center_links_response = ( + merchant_center_link_service.list_merchant_center_links( + customer_id=customer_id + ) ) number_of_links = len( diff --git a/examples/account_management/update_user_access.py b/examples/account_management/update_user_access.py index 00b4ecd29..db8c205a4 100755 --- a/examples/account_management/update_user_access.py +++ b/examples/account_management/update_user_access.py @@ -113,8 +113,10 @@ def modify_user_access(client, customer_id, user_id, access_role): customer_user_access_op = client.get_type("CustomerUserAccessOperation") access_role_enum = client.enums.AccessRoleEnum customer_user_access = customer_user_access_op.update - customer_user_access.resource_name = customer_user_access_service.customer_user_access_path( - customer_id, user_id + customer_user_access.resource_name = ( + customer_user_access_service.customer_user_access_path( + customer_id, user_id + ) ) customer_user_access.access_role = getattr(access_role_enum, access_role) client.copy_from( @@ -135,7 +137,7 @@ def modify_user_access(client, customer_id, user_id, access_role): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="This code example updates the access role of a user, " diff --git a/examples/advanced_operations/add_ad_customizer.py b/examples/advanced_operations/add_ad_customizer.py index 98f8519df..e6c3bd3a4 100755 --- a/examples/advanced_operations/add_ad_customizer.py +++ b/examples/advanced_operations/add_ad_customizer.py @@ -263,7 +263,7 @@ def create_ad_with_customizations( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( @@ -281,7 +281,11 @@ def create_ad_with_customizations( help="The Google Ads customer ID.", ) parser.add_argument( - "-a", "--ad_group_id", type=str, required=True, help="An ad group ID.", + "-a", + "--ad_group_id", + type=str, + required=True, + help="An ad group ID.", ) args = parser.parse_args() diff --git a/examples/advanced_operations/add_ad_group_bid_modifier.py b/examples/advanced_operations/add_ad_group_bid_modifier.py index 06e555125..4915f9def 100755 --- a/examples/advanced_operations/add_ad_group_bid_modifier.py +++ b/examples/advanced_operations/add_ad_group_bid_modifier.py @@ -51,7 +51,8 @@ def main(client, customer_id, ad_group_id, bid_modifier_value): # Add the ad group bid modifier. ad_group_bm_response = ad_group_bm_service.mutate_ad_group_bid_modifiers( - customer_id=customer_id, operations=[ad_group_bid_modifier_operation], + customer_id=customer_id, + operations=[ad_group_bid_modifier_operation], ) # [END add_ad_group_bid_modifier] @@ -64,7 +65,7 @@ def main(client, customer_id, ad_group_id, bid_modifier_value): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/advanced_operations/add_app_campaign.py b/examples/advanced_operations/add_app_campaign.py index fe353dbd9..8c976cdbd 100755 --- a/examples/advanced_operations/add_app_campaign.py +++ b/examples/advanced_operations/add_app_campaign.py @@ -183,8 +183,8 @@ def set_campaign_targeting_criteria( ) campaign_criterion = campaign_criterion_operation.create campaign_criterion.campaign = campaign_resource_name - campaign_criterion.location.geo_target_constant = geo_target_constant_service.geo_target_constant_path( - location_id + campaign_criterion.location.geo_target_constant = ( + geo_target_constant_service.geo_target_constant_path(location_id) ) campaign_criterion_operations.append(campaign_criterion_operation) @@ -195,8 +195,8 @@ def set_campaign_targeting_criteria( ) campaign_criterion = campaign_criterion_operation.create campaign_criterion.campaign = campaign_resource_name - campaign_criterion.language.language_constant = googleads_service.language_constant_path( - language_id + campaign_criterion.language.language_constant = ( + googleads_service.language_constant_path(language_id) ) campaign_criterion_operations.append(campaign_criterion_operation) @@ -295,7 +295,7 @@ def create_ad_text_asset(client, text): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/advanced_operations/add_bidding_data_exclusion.py b/examples/advanced_operations/add_bidding_data_exclusion.py index 81baa93dd..bfb0c7eb0 100755 --- a/examples/advanced_operations/add_bidding_data_exclusion.py +++ b/examples/advanced_operations/add_bidding_data_exclusion.py @@ -80,7 +80,7 @@ def main(client, customer_id, start_date_time, end_date_time): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds a data exclusion for conversions in Smart Bidding " diff --git a/examples/advanced_operations/add_bidding_seasonality_adjustment.py b/examples/advanced_operations/add_bidding_seasonality_adjustment.py index af22af72d..f67759c25 100755 --- a/examples/advanced_operations/add_bidding_seasonality_adjustment.py +++ b/examples/advanced_operations/add_bidding_seasonality_adjustment.py @@ -94,7 +94,7 @@ def main( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds a seasonality adjustment for conversions in Smart " diff --git a/examples/advanced_operations/add_call_ad.py b/examples/advanced_operations/add_call_ad.py index 2438ea447..8ad86fd43 100755 --- a/examples/advanced_operations/add_call_ad.py +++ b/examples/advanced_operations/add_call_ad.py @@ -101,7 +101,7 @@ def main( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Adds a call extension to a specific account.") @@ -115,7 +115,11 @@ def main( help="The Google Ads customer ID.", ) parser.add_argument( - "-a", "--ad_group_id", type=str, required=True, help="An ad group ID.", + "-a", + "--ad_group_id", + type=str, + required=True, + help="An ad group ID.", ) parser.add_argument( "-n", diff --git a/examples/advanced_operations/add_display_upload_ad.py b/examples/advanced_operations/add_display_upload_ad.py index af6de42f6..bac18ebf5 100644 --- a/examples/advanced_operations/add_display_upload_ad.py +++ b/examples/advanced_operations/add_display_upload_ad.py @@ -150,7 +150,7 @@ def create_display_upload_ad_group_ad( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds a display upload ad to a given ad group." diff --git a/examples/advanced_operations/add_dynamic_page_feed_asset.py b/examples/advanced_operations/add_dynamic_page_feed_asset.py index 33e6bbaa5..e92adc02b 100755 --- a/examples/advanced_operations/add_dynamic_page_feed_asset.py +++ b/examples/advanced_operations/add_dynamic_page_feed_asset.py @@ -260,11 +260,13 @@ def add_dsa_target(client, customer_id, ad_group_id, dsa_page_url_label): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") - parser = argparse.ArgumentParser(description=( - "Adds a page feed with URLs for a Dynamic Search Ads campaign" - )) + parser = argparse.ArgumentParser( + description=( + "Adds a page feed with URLs for a Dynamic Search Ads campaign" + ) + ) # The following argument(s) should be provided to run the example. parser.add_argument( "-c", diff --git a/examples/advanced_operations/add_dynamic_search_ads.py b/examples/advanced_operations/add_dynamic_search_ads.py index 1eae4ba1c..72e738bca 100755 --- a/examples/advanced_operations/add_dynamic_search_ads.py +++ b/examples/advanced_operations/add_dynamic_search_ads.py @@ -260,7 +260,7 @@ def add_webpage_criterion(client, customer_id, ad_group_resource_name): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/advanced_operations/add_performance_max_campaign.py b/examples/advanced_operations/add_performance_max_campaign.py index 24b8e5ce4..07833c7e6 100644 --- a/examples/advanced_operations/add_performance_max_campaign.py +++ b/examples/advanced_operations/add_performance_max_campaign.py @@ -75,11 +75,22 @@ def main(client, customer_id, audience_id): # # Create the headlines. headline_asset_resource_names = create_multiple_text_assets( - client, customer_id, ["Travel", "Travel Reviews", "Book travel",], + client, + customer_id, + [ + "Travel", + "Travel Reviews", + "Book travel", + ], ) # Create the descriptions. description_asset_resource_names = create_multiple_text_assets( - client, customer_id, ["Take to the air!", "Fly to the sky!",], + client, + customer_id, + [ + "Take to the air!", + "Fly to the sky!", + ], ) # The below methods create and return MutateOperations that we later @@ -90,13 +101,18 @@ def main(client, customer_id, audience_id): # successfully or fail entirely, leaving no orphaned entities. See: # https://developers.google.com/google-ads/api/docs/mutating/overview campaign_budget_operation = create_campaign_budget_operation( - client, customer_id, + client, + customer_id, ) - performance_max_campaign_operation = create_performance_max_campaign_operation( - client, customer_id, + performance_max_campaign_operation = ( + create_performance_max_campaign_operation( + client, + customer_id, + ) ) campaign_criterion_operations = create_campaign_criterion_operations( - client, customer_id, + client, + customer_id, ) asset_group_operations = create_asset_group_operation( client, @@ -135,7 +151,8 @@ def main(client, customer_id, audience_id): # [START add_performance_max_campaign_2] def create_campaign_budget_operation( - client, customer_id, + client, + customer_id, ): """Creates a MutateOperation that creates a new CampaignBudget. @@ -173,7 +190,8 @@ def create_campaign_budget_operation( # [START add_performance_max_campaign_3] def create_performance_max_campaign_operation( - client, customer_id, + client, + customer_id, ): """Creates a MutateOperation that creates a new Performance Max campaign. @@ -242,7 +260,8 @@ def create_performance_max_campaign_operation( # [START add_performance_max_campaign_4] def create_campaign_criterion_operations( - client, customer_id, + client, + customer_id, ): """Creates a list of MutateOperations that create new campaign criteria. @@ -273,8 +292,8 @@ def create_campaign_criterion_operations( campaign_criterion.campaign = campaign_service.campaign_path( customer_id, _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID ) - campaign_criterion.location.geo_target_constant = geo_target_constant_service.geo_target_constant_path( - "1023191" + campaign_criterion.location.geo_target_constant = ( + geo_target_constant_service.geo_target_constant_path("1023191") ) campaign_criterion.negative = False operations.append(mutate_operation) @@ -285,8 +304,8 @@ def create_campaign_criterion_operations( campaign_criterion.campaign = campaign_service.campaign_path( customer_id, _PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID ) - campaign_criterion.location.geo_target_constant = geo_target_constant_service.geo_target_constant_path( - "1022762" + campaign_criterion.location.geo_target_constant = ( + geo_target_constant_service.geo_target_constant_path("1022762") ) campaign_criterion.negative = True operations.append(mutate_operation) @@ -300,8 +319,8 @@ def create_campaign_criterion_operations( # Set the language. # For a list of all language codes, see: # https://developers.google.com/google-ads/api/reference/data/codes-formats#expandable-7 - campaign_criterion.language.language_constant = googleads_service.language_constant_path( - "1000" + campaign_criterion.language.language_constant = ( + googleads_service.language_constant_path("1000") ) # English operations.append(mutate_operation) @@ -335,7 +354,8 @@ def create_multiple_text_assets(client, customer_id, texts): # Send the operations in a single Mutate request. response = googleads_service.mutate( - customer_id=customer_id, mutate_operations=operations, + customer_id=customer_id, + mutate_operations=operations, ) asset_resource_names = [] for result in response.mutate_operation_responses: @@ -383,7 +403,8 @@ def create_asset_group_operation( asset_group.final_mobile_urls.append("http://www.example.com") asset_group.status = client.enums.AssetGroupStatusEnum.PAUSED asset_group.resource_name = asset_group_service.asset_group_path( - customer_id, _ASSET_GROUP_TEMPORARY_ID, + customer_id, + _ASSET_GROUP_TEMPORARY_ID, ) operations.append(mutate_operation) @@ -407,7 +428,8 @@ def create_asset_group_operation( asset_group_asset = mutate_operation.asset_group_asset_operation.create asset_group_asset.field_type = client.enums.AssetFieldTypeEnum.HEADLINE asset_group_asset.asset_group = asset_group_service.asset_group_path( - customer_id, _ASSET_GROUP_TEMPORARY_ID, + customer_id, + _ASSET_GROUP_TEMPORARY_ID, ) asset_group_asset.asset = resource_name operations.append(mutate_operation) @@ -420,7 +442,8 @@ def create_asset_group_operation( client.enums.AssetFieldTypeEnum.DESCRIPTION ) asset_group_asset.asset_group = asset_group_service.asset_group_path( - customer_id, _ASSET_GROUP_TEMPORARY_ID, + customer_id, + _ASSET_GROUP_TEMPORARY_ID, ) asset_group_asset.asset = resource_name operations.append(mutate_operation) @@ -508,7 +531,8 @@ def create_and_link_text_asset(client, customer_id, text, field_type): asset_group_asset = mutate_operation.asset_group_asset_operation.create asset_group_asset.field_type = field_type asset_group_asset.asset_group = asset_group_service.asset_group_path( - customer_id, _ASSET_GROUP_TEMPORARY_ID, + customer_id, + _ASSET_GROUP_TEMPORARY_ID, ) asset_group_asset.asset = asset_service.asset_path( customer_id, next_temp_id @@ -558,7 +582,8 @@ def create_and_link_image_asset( asset_group_asset = mutate_operation.asset_group_asset_operation.create asset_group_asset.field_type = field_type asset_group_asset.asset_group = asset_group_service.asset_group_path( - customer_id, _ASSET_GROUP_TEMPORARY_ID, + customer_id, + _ASSET_GROUP_TEMPORARY_ID, ) asset_group_asset.asset = asset_service.asset_path( customer_id, next_temp_id @@ -645,7 +670,7 @@ def create_asset_group_signal_operation(client, customer_id, audience_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Creates a Performance Max campaign.") @@ -659,7 +684,10 @@ def create_asset_group_signal_operation(client, customer_id, audience_id): help="The Google Ads customer ID.", ) parser.add_argument( - "-a", "--audience_id", type=str, help="The ID of an audience.", + "-a", + "--audience_id", + type=str, + help="The ID of an audience.", ) args = parser.parse_args() diff --git a/examples/advanced_operations/add_responsive_search_ad_full.py b/examples/advanced_operations/add_responsive_search_ad_full.py index 7426be7c7..7ccf63401 100644 --- a/examples/advanced_operations/add_responsive_search_ad_full.py +++ b/examples/advanced_operations/add_responsive_search_ad_full.py @@ -370,8 +370,11 @@ def add_keywords(client, customer_id, ad_group_resource_name): campaign_criterion_operations = operations # Add keywords - ad_group_criterion_response = ad_group_criterion_service.mutate_ad_group_criteria( - customer_id=customer_id, operations=[*campaign_criterion_operations], + ad_group_criterion_response = ( + ad_group_criterion_service.mutate_ad_group_criteria( + customer_id=customer_id, + operations=[*campaign_criterion_operations], + ) ) for result in ad_group_criterion_response.results: print("Created keyword " f"{result.resource_name}.") @@ -431,8 +434,10 @@ def add_geo_targeting(client, customer_id, campaign_resource_name): operations.append(campaign_criterion_operation) campaign_criterion_service = client.get_service("CampaignCriterionService") - campaign_criterion_response = campaign_criterion_service.mutate_campaign_criteria( - customer_id=customer_id, operations=[*operations] + campaign_criterion_response = ( + campaign_criterion_service.mutate_campaign_criteria( + customer_id=customer_id, operations=[*operations] + ) ) for result in campaign_criterion_response.results: @@ -485,8 +490,10 @@ def add_images(client, customer_id, campaign_resource_name): extension_feed_item = extension_feed_item_operation.create extension_feed_item.image_feed_item.image_asset = image_asset_resource_name - extension_feed_response = extension_feed_item_service.mutate_extension_feed_items( - customer_id=customer_id, operations=[extension_feed_item_operation] + extension_feed_response = ( + extension_feed_item_service.mutate_extension_feed_items( + customer_id=customer_id, operations=[extension_feed_item_operation] + ) ) image_resource_name = extension_feed_response.results[0].resource_name @@ -507,9 +514,11 @@ def add_images(client, customer_id, campaign_resource_name): ces.extension_type = client.enums.ExtensionTypeEnum.IMAGE ces.extension_feed_items.append(image_resource_name) - campaign_extension_response = campaign_extension_setting_service.mutate_campaign_extension_settings( - customer_id=customer_id, - operations=[campaign_extension_setting_operation], + campaign_extension_response = ( + campaign_extension_setting_service.mutate_campaign_extension_settings( + customer_id=customer_id, + operations=[campaign_extension_setting_operation], + ) ) print( @@ -521,7 +530,7 @@ def add_images(client, customer_id, campaign_resource_name): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Creates a Responsive Search Ad for specified customer.") diff --git a/examples/advanced_operations/add_responsive_search_ad_with_ad_customizer.py b/examples/advanced_operations/add_responsive_search_ad_with_ad_customizer.py index 84b8ec15a..fc6cf364a 100755 --- a/examples/advanced_operations/add_responsive_search_ad_with_ad_customizer.py +++ b/examples/advanced_operations/add_responsive_search_ad_with_ad_customizer.py @@ -210,7 +210,7 @@ def create_responsive_search_ad_with_customization( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( @@ -226,7 +226,11 @@ def create_responsive_search_ad_with_customization( help="The Google Ads customer ID.", ) parser.add_argument( - "-a", "--ad_group_id", type=str, required=True, help="An ad group ID.", + "-a", + "--ad_group_id", + type=str, + required=True, + help="An ad group ID.", ) parser.add_argument( "-n", diff --git a/examples/advanced_operations/add_smart_campaign.py b/examples/advanced_operations/add_smart_campaign.py index 4dd9ff3bf..8d99c273c 100755 --- a/examples/advanced_operations/add_smart_campaign.py +++ b/examples/advanced_operations/add_smart_campaign.py @@ -811,7 +811,7 @@ def print_response_details(response): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser(description=("Creates a Smart campaign.")) # The following argument(s) should be provided to run the example. 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 f69f3534a..945245d8c 100755 --- a/examples/advanced_operations/create_and_attach_shared_keyword_set.py +++ b/examples/advanced_operations/create_and_attach_shared_keyword_set.py @@ -81,8 +81,10 @@ def main(client, customer_id, campaign_id): campaign_set.shared_set = shared_set_resource_name try: - campaign_shared_set_resource_name = campaign_shared_set_service.mutate_campaign_shared_sets( - customer_id=customer_id, operations=[campaign_set_operation] + campaign_shared_set_resource_name = ( + campaign_shared_set_service.mutate_campaign_shared_sets( + customer_id=customer_id, operations=[campaign_set_operation] + ) ) print( @@ -109,7 +111,7 @@ def handle_googleads_exception(exception): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( 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 2a7c059e8..2924c5121 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 @@ -135,7 +135,7 @@ def handle_googleads_exception(exception): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/advanced_operations/get_ad_group_bid_modifiers.py b/examples/advanced_operations/get_ad_group_bid_modifiers.py index 0f4a0340a..298673d65 100755 --- a/examples/advanced_operations/get_ad_group_bid_modifiers.py +++ b/examples/advanced_operations/get_ad_group_bid_modifiers.py @@ -96,7 +96,7 @@ def main(client, customer_id, page_size, ad_group_id=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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="List ad group bid modifiers for specified customer." diff --git a/examples/advanced_operations/use_cross_account_bidding_strategy.py b/examples/advanced_operations/use_cross_account_bidding_strategy.py index f39062287..c3a55f655 100755 --- a/examples/advanced_operations/use_cross_account_bidding_strategy.py +++ b/examples/advanced_operations/use_cross_account_bidding_strategy.py @@ -219,7 +219,7 @@ def attach_cross_account_bidding_strategy_to_campaign( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser(description=("Creates a Smart campaign.")) # The following argument(s) should be provided to run the example. diff --git a/examples/advanced_operations/use_portfolio_bidding_strategy.py b/examples/advanced_operations/use_portfolio_bidding_strategy.py index 15baa9105..c857ad8ce 100755 --- a/examples/advanced_operations/use_portfolio_bidding_strategy.py +++ b/examples/advanced_operations/use_portfolio_bidding_strategy.py @@ -41,8 +41,10 @@ def main(client, customer_id): # Add budget. try: - campaign_budget_response = campaign_budget_service.mutate_campaign_budgets( - customer_id=customer_id, operations=[campaign_budget_operation] + campaign_budget_response = ( + campaign_budget_service.mutate_campaign_budgets( + customer_id=customer_id, operations=[campaign_budget_operation] + ) ) campaign_budget_id = campaign_budget_response.results[0].resource_name print(f'Budget "{campaign_budget_id}" was created.') @@ -60,8 +62,10 @@ def main(client, customer_id): # Add portfolio bidding strategy. try: - bidding_strategy_response = bidding_strategy_service.mutate_bidding_strategies( - customer_id=customer_id, operations=[bidding_strategy_operation] + bidding_strategy_response = ( + bidding_strategy_service.mutate_bidding_strategies( + customer_id=customer_id, operations=[bidding_strategy_operation] + ) ) bidding_strategy_id = bidding_strategy_response.results[0].resource_name print(f'Created portfolio bidding strategy "{bidding_strategy_id}".') @@ -121,7 +125,7 @@ def handle_googleads_exception(exception): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds a campaign for specified customer." diff --git a/examples/basic_operations/add_ad_groups.py b/examples/basic_operations/add_ad_groups.py index 9c2b84310..69736acb5 100755 --- a/examples/basic_operations/add_ad_groups.py +++ b/examples/basic_operations/add_ad_groups.py @@ -49,7 +49,7 @@ def main(client, customer_id, campaign_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds an ad group for specified customer and campaign id." diff --git a/examples/basic_operations/add_campaigns.py b/examples/basic_operations/add_campaigns.py index 292c6cbba..e7935c57f 100755 --- a/examples/basic_operations/add_campaigns.py +++ b/examples/basic_operations/add_campaigns.py @@ -46,8 +46,10 @@ def main(client, customer_id): # Add budget. try: - campaign_budget_response = campaign_budget_service.mutate_campaign_budgets( - customer_id=customer_id, operations=[campaign_budget_operation] + campaign_budget_response = ( + campaign_budget_service.mutate_campaign_budgets( + customer_id=customer_id, operations=[campaign_budget_operation] + ) ) except GoogleAdsException as ex: handle_googleads_exception(ex) @@ -114,7 +116,7 @@ def handle_googleads_exception(exception): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds a campaign for specified customer." diff --git a/examples/basic_operations/get_campaigns.py b/examples/basic_operations/get_campaigns.py index 0aa245b5c..ee1d82461 100755 --- a/examples/basic_operations/get_campaigns.py +++ b/examples/basic_operations/get_campaigns.py @@ -46,10 +46,11 @@ def main(client, customer_id): ) # [END get_campaigns] + 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Lists all campaigns for specified customer." diff --git a/examples/basic_operations/get_responsive_search_ads.py b/examples/basic_operations/get_responsive_search_ads.py index c625093fc..8415906fa 100755 --- a/examples/basic_operations/get_responsive_search_ads.py +++ b/examples/basic_operations/get_responsive_search_ads.py @@ -83,7 +83,7 @@ def ad_text_assets_to_strs(assets): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="List responsive display ads for specified customer. " diff --git a/examples/basic_operations/pause_ad.py b/examples/basic_operations/pause_ad.py index ee15c712b..2d7a80fe2 100755 --- a/examples/basic_operations/pause_ad.py +++ b/examples/basic_operations/pause_ad.py @@ -50,7 +50,7 @@ def main(client, customer_id, ad_group_id, ad_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Pauses an ad in the specified customer's ad group.") ) diff --git a/examples/basic_operations/remove_campaign.py b/examples/basic_operations/remove_campaign.py index be8593ed5..7c8d6fd5f 100755 --- a/examples/basic_operations/remove_campaign.py +++ b/examples/basic_operations/remove_campaign.py @@ -39,7 +39,7 @@ def main(client, customer_id, campaign_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Removes given campaign for the specified customer.") diff --git a/examples/basic_operations/search_for_google_ads_fields.py b/examples/basic_operations/search_for_google_ads_fields.py index 0ccec97a9..9f53098de 100755 --- a/examples/basic_operations/search_for_google_ads_fields.py +++ b/examples/basic_operations/search_for_google_ads_fields.py @@ -96,7 +96,7 @@ def main(client, name_prefix, page_size): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Lists metadata for the specified artifact." diff --git a/examples/basic_operations/update_ad_group.py b/examples/basic_operations/update_ad_group.py index ebb00e65a..e71f0ac7b 100755 --- a/examples/basic_operations/update_ad_group.py +++ b/examples/basic_operations/update_ad_group.py @@ -55,7 +55,7 @@ def main(client, customer_id, ad_group_id, cpc_bid_micro_amount): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/basic_operations/update_campaign.py b/examples/basic_operations/update_campaign.py index ae7e11aaf..e1fff3b87 100755 --- a/examples/basic_operations/update_campaign.py +++ b/examples/basic_operations/update_campaign.py @@ -55,7 +55,7 @@ def main(client, customer_id, campaign_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Updates the given campaign for the specified customer." diff --git a/examples/basic_operations/update_responsive_search_ad.py b/examples/basic_operations/update_responsive_search_ad.py index 0818659fc..1d7486e73 100755 --- a/examples/basic_operations/update_responsive_search_ad.py +++ b/examples/basic_operations/update_responsive_search_ad.py @@ -79,7 +79,7 @@ def main(client, customer_id, ad_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/billing/add_account_budget_proposal.py b/examples/billing/add_account_budget_proposal.py index 311de6d6a..e0bc6ef69 100755 --- a/examples/billing/add_account_budget_proposal.py +++ b/examples/billing/add_account_budget_proposal.py @@ -64,8 +64,11 @@ def main(client, customer_id, billing_setup_id): # proposal.proposed_notes = 'Received prepayment of $0.01' proposal.proposed_spending_limit_micros = 10000 - account_budget_proposal_response = account_budget_proposal_service.mutate_account_budget_proposal( - customer_id=customer_id, operation=account_budget_proposal_operation, + account_budget_proposal_response = ( + account_budget_proposal_service.mutate_account_budget_proposal( + customer_id=customer_id, + operation=account_budget_proposal_operation, + ) ) print( "Created account budget proposal " @@ -77,7 +80,7 @@ def main(client, customer_id, billing_setup_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Creates an account budget proposal." diff --git a/examples/billing/add_billing_setup.py b/examples/billing/add_billing_setup.py index 39a1f3f7a..5e8d6bb4a 100755 --- a/examples/billing/add_billing_setup.py +++ b/examples/billing/add_billing_setup.py @@ -185,7 +185,7 @@ def set_billing_setup_date_times(client, customer_id, billing_setup): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Creates a billing setup for a given customer.") diff --git a/examples/billing/get_invoices.py b/examples/billing/get_invoices.py index 21f05a8d8..b016de564 100755 --- a/examples/billing/get_invoices.py +++ b/examples/billing/get_invoices.py @@ -107,7 +107,7 @@ def micros_to_currency(micros): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Retrieves the invoices issued last month for a given billing setup." diff --git a/examples/campaign_management/add_campaign_labels.py b/examples/campaign_management/add_campaign_labels.py index 5ed325496..e227bf88f 100755 --- a/examples/campaign_management/add_campaign_labels.py +++ b/examples/campaign_management/add_campaign_labels.py @@ -68,7 +68,7 @@ def main(client, customer_id, label_id, campaign_ids): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="This code example adds a campaign label to a list of " 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 d283c8ffa..2b28cbf06 100755 --- a/examples/campaign_management/add_complete_campaigns_using_batch_job.py +++ b/examples/campaign_management/add_complete_campaigns_using_batch_job.py @@ -631,7 +631,7 @@ def handle_googleads_exception(exception): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/campaign_management/create_experiment.py b/examples/campaign_management/create_experiment.py index 8aa17050e..eb7eae3ed 100644 --- a/examples/campaign_management/create_experiment.py +++ b/examples/campaign_management/create_experiment.py @@ -185,7 +185,7 @@ def modify_draft_campaign(client, customer_id, draft_campaign): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Create a campaign experiment based on a campaign draft.") diff --git a/examples/campaign_management/get_all_disapproved_ads.py b/examples/campaign_management/get_all_disapproved_ads.py index 0c04a5f8c..cf80c4162 100755 --- a/examples/campaign_management/get_all_disapproved_ads.py +++ b/examples/campaign_management/get_all_disapproved_ads.py @@ -80,7 +80,7 @@ def main(client, customer_id, campaign_id, page_size): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/campaign_management/set_ad_parameters.py b/examples/campaign_management/set_ad_parameters.py index 0ba27e96e..1dd710493 100755 --- a/examples/campaign_management/set_ad_parameters.py +++ b/examples/campaign_management/set_ad_parameters.py @@ -99,7 +99,7 @@ def create_ad_parameter(client, resource_name, parameter_index, insertion_text): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") # Initializes a command line argument parser. parser = argparse.ArgumentParser( diff --git a/examples/campaign_management/update_campaign_criterion_bid_modifier.py b/examples/campaign_management/update_campaign_criterion_bid_modifier.py index 68fe5c64a..bb544a258 100755 --- a/examples/campaign_management/update_campaign_criterion_bid_modifier.py +++ b/examples/campaign_management/update_campaign_criterion_bid_modifier.py @@ -38,8 +38,11 @@ def main(client, customer_id, campaign_id, criterion_id, bid_modifier_value): protobuf_helpers.field_mask(None, campaign_criterion._pb), ) - campaign_criterion_response = campaign_criterion_service.mutate_campaign_criteria( - customer_id=customer_id, operations=[campaign_criterion_operation], + campaign_criterion_response = ( + campaign_criterion_service.mutate_campaign_criteria( + customer_id=customer_id, + operations=[campaign_criterion_operation], + ) ) print( @@ -52,7 +55,7 @@ def main(client, customer_id, campaign_id, criterion_id, bid_modifier_value): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/campaign_management/validate_ad.py b/examples/campaign_management/validate_ad.py index bac6fa2df..27a85d225 100755 --- a/examples/campaign_management/validate_ad.py +++ b/examples/campaign_management/validate_ad.py @@ -114,7 +114,7 @@ def main(client, customer_id, ad_group_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/custom_logging_interceptor/get_campaigns.py b/examples/custom_logging_interceptor/get_campaigns.py index 80ae9fdc6..569b820c2 100755 --- a/examples/custom_logging_interceptor/get_campaigns.py +++ b/examples/custom_logging_interceptor/get_campaigns.py @@ -24,7 +24,7 @@ from google.ads.googleads.errors import GoogleAdsException from cloud_logging_interceptor import CloudLoggingInterceptor -_API_VERSION = "v14" +_API_VERSION = "v15" def main(client, customer_id): diff --git a/examples/error_handling/handle_keyword_policy_violations.py b/examples/error_handling/handle_keyword_policy_violations.py index 1878288fb..3d33cccda 100755 --- a/examples/error_handling/handle_keyword_policy_violations.py +++ b/examples/error_handling/handle_keyword_policy_violations.py @@ -226,7 +226,7 @@ def request_exemption( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Demonstrates how to request an exemption for policy " diff --git a/examples/error_handling/handle_partial_failure.py b/examples/error_handling/handle_partial_failure.py index ea8f60561..2c0b2c6ab 100755 --- a/examples/error_handling/handle_partial_failure.py +++ b/examples/error_handling/handle_partial_failure.py @@ -207,7 +207,7 @@ def print_results(client, response): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds an ad group for specified customer and campaign id." diff --git a/examples/error_handling/handle_rate_exceeded_error.py b/examples/error_handling/handle_rate_exceeded_error.py index a77e45f5a..d71f2d2a7 100755 --- a/examples/error_handling/handle_rate_exceeded_error.py +++ b/examples/error_handling/handle_rate_exceeded_error.py @@ -174,7 +174,7 @@ def request_mutate_and_display_result(client, customer_id, operations): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Handles RateExceededError in an application.." 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 902ab357e..f7c4f7a14 100755 --- a/examples/error_handling/handle_responsive_search_ad_policy_violations.py +++ b/examples/error_handling/handle_responsive_search_ad_policy_violations.py @@ -205,7 +205,7 @@ def request_exemption( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Requests an exemption for responsive search ad policy " diff --git a/examples/extensions/add_affiliate_location_extensions.py b/examples/extensions/add_affiliate_location_extensions.py index 6c4bec0ee..462ed37b0 100644 --- a/examples/extensions/add_affiliate_location_extensions.py +++ b/examples/extensions/add_affiliate_location_extensions.py @@ -331,7 +331,7 @@ def wait_for_feed_to_be_ready(client, customer_id, feed_resource_name): if feed_mapping is None: num_attempts += 1 - sleep_seconds = 5 * 2 ** num_attempts + sleep_seconds = 5 * 2**num_attempts print( f"Checked {num_attempts} time(s). Feed is not ready " f"yet. Waiting {sleep_seconds} seconds before trying again." @@ -390,8 +390,10 @@ def create_campaign_feed( "CampaignService" ).campaign_path(customer_id, campaign_id) - mutate_campaign_feeds_response = campaign_feed_service.mutate_campaign_feeds( - customer_id=customer_id, operations=[campaign_feed_operation] + mutate_campaign_feeds_response = ( + campaign_feed_service.mutate_campaign_feeds( + customer_id=customer_id, operations=[campaign_feed_operation] + ) ) # Display the result. @@ -432,7 +434,7 @@ def get_attribute_id_for_chain_id(client, feed_mapping): if __name__ == "__main__": # will read the google-ads.yaml configuration file in the # home directory if none is specified. - googleads_client = GoogleAdsClient.load_from_storage(version="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Demonstrates how to add Affiliate Location extensions." @@ -466,7 +468,10 @@ def get_attribute_id_for_chain_id(client, feed_mapping): try: main( - googleads_client, args.customer_id, args.chain_id, args.campaign_id, + googleads_client, + args.customer_id, + args.chain_id, + args.campaign_id, ) except GoogleAdsException as ex: print( diff --git a/examples/extensions/add_business_profile_location_extensions.py b/examples/extensions/add_business_profile_location_extensions.py index 464757953..3bbfa2f41 100644 --- a/examples/extensions/add_business_profile_location_extensions.py +++ b/examples/extensions/add_business_profile_location_extensions.py @@ -138,7 +138,7 @@ def main( if feed_mapping is None: number_of_attempts += 1 - sleep_seconds = 5 * (2 ** number_of_attempts) + sleep_seconds = 5 * (2**number_of_attempts) print( f"Attempt #{number_of_attempts} was not successful. " @@ -357,7 +357,7 @@ def get_business_profile_feed_mapping(client, customer_id, feed_resource_name): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds a feed that syncs feed items from a Business Profile " diff --git a/examples/extensions/add_call.py b/examples/extensions/add_call.py index 72d4c979d..bb0604380 100755 --- a/examples/extensions/add_call.py +++ b/examples/extensions/add_call.py @@ -123,7 +123,7 @@ def link_asset_to_account(client, customer_id, asset_resource_name): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Adds a call extension to a specific account.") diff --git a/examples/extensions/add_geo_target.py b/examples/extensions/add_geo_target.py index 5a637559d..7f0a368ef 100755 --- a/examples/extensions/add_geo_target.py +++ b/examples/extensions/add_geo_target.py @@ -43,8 +43,10 @@ def main(client, customer_id, feed_item_id, geo_target_constant_id): extension_feed_item = extension_feed_item_operation.update # Creates an extension feed item using the specified feed item ID and # geo target constant ID for targeting. - extension_feed_item.resource_name = extension_feed_item_service.extension_feed_item_path( - customer_id, feed_item_id + extension_feed_item.resource_name = ( + extension_feed_item_service.extension_feed_item_path( + customer_id, feed_item_id + ) ) extension_feed_item.targeted_geo_target_constant = client.get_service( "GeoTargetConstantService" @@ -67,7 +69,7 @@ def main(client, customer_id, feed_item_id, geo_target_constant_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds a geo target to an extension feed item for targeting." diff --git a/examples/extensions/add_hotel_callout.py b/examples/extensions/add_hotel_callout.py index 70bf62763..e9326dd21 100755 --- a/examples/extensions/add_hotel_callout.py +++ b/examples/extensions/add_hotel_callout.py @@ -110,7 +110,7 @@ def link_asset_to_account(client, customer_id, resource_names): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds a hotel callout extension asset to the given account." diff --git a/examples/extensions/add_image_extension.py b/examples/extensions/add_image_extension.py index c833b1b39..09a1228ac 100755 --- a/examples/extensions/add_image_extension.py +++ b/examples/extensions/add_image_extension.py @@ -66,9 +66,11 @@ def main(client, customer_id, campaign_id, image_asset_id): ces.extension_type = client.enums.ExtensionTypeEnum.IMAGE ces.extension_feed_items.append(image_resource_name) - response = campaign_extension_setting_service.mutate_campaign_extension_settings( - customer_id=customer_id, - operations=[campaign_extension_setting_operation], + response = ( + campaign_extension_setting_service.mutate_campaign_extension_settings( + customer_id=customer_id, + operations=[campaign_extension_setting_operation], + ) ) print( "Created a campaign extension setting with resource name: " @@ -79,7 +81,7 @@ def main(client, customer_id, campaign_id, image_asset_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Adds an image extension to a campaign.") diff --git a/examples/extensions/add_lead_form_extension.py b/examples/extensions/add_lead_form_extension.py index fbbef7452..046ecc8f8 100755 --- a/examples/extensions/add_lead_form_extension.py +++ b/examples/extensions/add_lead_form_extension.py @@ -173,7 +173,7 @@ def create_lead_form_extension( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="This code example creates a lead form and a lead form " diff --git a/examples/extensions/add_prices.py b/examples/extensions/add_prices.py index 5806307fd..e9c01bc79 100644 --- a/examples/extensions/add_prices.py +++ b/examples/extensions/add_prices.py @@ -184,7 +184,7 @@ def add_asset_to_account(client, customer_id, price_asset_resource_name): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Add price asset for the specified customer id." diff --git a/examples/extensions/add_sitelinks.py b/examples/extensions/add_sitelinks.py index 79d98ca37..078e07795 100755 --- a/examples/extensions/add_sitelinks.py +++ b/examples/extensions/add_sitelinks.py @@ -216,7 +216,7 @@ def populate_ad_schedule( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds sitelinks to the specified campaign." diff --git a/examples/extensions/add_sitelinks_using_assets.py b/examples/extensions/add_sitelinks_using_assets.py index 66f7ade2c..b3eda70be 100755 --- a/examples/extensions/add_sitelinks_using_assets.py +++ b/examples/extensions/add_sitelinks_using_assets.py @@ -139,7 +139,7 @@ def link_sitelinks_to_campaign( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds sitelinks to a campaign using feed services." diff --git a/examples/extensions/migrate_promotion_feed_to_asset.py b/examples/extensions/migrate_promotion_feed_to_asset.py index 2aa7e3950..dc4b59b3c 100755 --- a/examples/extensions/migrate_promotion_feed_to_asset.py +++ b/examples/extensions/migrate_promotion_feed_to_asset.py @@ -409,7 +409,7 @@ def associate_asset_with_ad_groups( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Migrates a feed-based promotion extension to an " diff --git a/examples/extensions/remove_entire_sitelink_campaign_extension_setting.py b/examples/extensions/remove_entire_sitelink_campaign_extension_setting.py index a9f4666ec..2f76b1d85 100644 --- a/examples/extensions/remove_entire_sitelink_campaign_extension_setting.py +++ b/examples/extensions/remove_entire_sitelink_campaign_extension_setting.py @@ -43,8 +43,10 @@ def main(client, customer_id, campaign_id): """ # Initialize an array of MutateOperations mutate_operations = [] - sitelink_campaign_extension_setting_mutate_operation = create_sitelink_campaign_extension_setting_mutate_operation( - client, customer_id, campaign_id + sitelink_campaign_extension_setting_mutate_operation = ( + create_sitelink_campaign_extension_setting_mutate_operation( + client, customer_id, campaign_id + ) ) mutate_operations.append( sitelink_campaign_extension_setting_mutate_operation @@ -54,8 +56,10 @@ def main(client, customer_id, campaign_id): extension_feed_item_resource_names = get_all_sitelink_extension_feed_items( client, ga_service, customer_id, campaign_id ) - extension_feed_item_mutate_operations = create_extension_feed_item_mutate_operations( - client, extension_feed_item_resource_names + extension_feed_item_mutate_operations = ( + create_extension_feed_item_mutate_operations( + client, extension_feed_item_resource_names + ) ) mutate_operations.extend(extension_feed_item_mutate_operations) @@ -197,7 +201,7 @@ def create_extension_feed_item_mutate_operations( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Removes the entire sitelink campaign extension setting." @@ -211,7 +215,11 @@ def create_extension_feed_item_mutate_operations( help="The Google Ads customer ID", ) parser.add_argument( - "-i", "--campaign_id", type=str, required=True, help="The campaign ID", + "-i", + "--campaign_id", + type=str, + required=True, + help="The campaign ID", ) args = parser.parse_args() diff --git a/examples/extensions/update_sitelink.py b/examples/extensions/update_sitelink.py index fa464d2cf..aa65c7f5a 100644 --- a/examples/extensions/update_sitelink.py +++ b/examples/extensions/update_sitelink.py @@ -40,8 +40,10 @@ def main(client, customer_id, feed_item_id, sitelink_text): ) extension_feed_item = extension_feed_item_operation.update # Update the extension feed item using the specified feed item ID - extension_feed_item.resource_name = extension_feed_item_service.extension_feed_item_path( - customer_id, feed_item_id + extension_feed_item.resource_name = ( + extension_feed_item_service.extension_feed_item_path( + customer_id, feed_item_id + ) ) extension_feed_item.sitelink_feed_item.link_text = sitelink_text @@ -65,7 +67,7 @@ def main(client, customer_id, feed_item_id, sitelink_text): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Update sitelink extension feed item with the specified " diff --git a/examples/extensions/update_sitelink_campaign_extension_setting.py b/examples/extensions/update_sitelink_campaign_extension_setting.py index 8fcd67635..f28b3cbcd 100644 --- a/examples/extensions/update_sitelink_campaign_extension_setting.py +++ b/examples/extensions/update_sitelink_campaign_extension_setting.py @@ -61,8 +61,10 @@ def main(client, customer_id, campaign_id, feed_item_ids): ) extension_type_enum = client.enums.ExtensionTypeEnum - resource_name = campaign_extension_setting_service.campaign_extension_setting_path( - customer_id, campaign_id, extension_type_enum.SITELINK.name + resource_name = ( + campaign_extension_setting_service.campaign_extension_setting_path( + customer_id, campaign_id, extension_type_enum.SITELINK.name + ) ) campaign_extension_setting.resource_name = resource_name @@ -73,9 +75,11 @@ def main(client, customer_id, campaign_id, feed_item_ids): ) # Update the campaign extension settings - response = campaign_extension_setting_service.mutate_campaign_extension_settings( - customer_id=customer_id, - operations=[campaign_extension_setting_operation], + response = ( + campaign_extension_setting_service.mutate_campaign_extension_settings( + customer_id=customer_id, + operations=[campaign_extension_setting_operation], + ) ) print( "Updated campaign extension setting with resource name: " @@ -87,7 +91,7 @@ def main(client, customer_id, campaign_id, feed_item_ids): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( @@ -104,7 +108,11 @@ def main(client, customer_id, campaign_id, feed_item_ids): help="The Google Ads customer ID", ) parser.add_argument( - "-i", "--campaign_id", type=str, required=True, help="The campaign ID", + "-i", + "--campaign_id", + type=str, + required=True, + help="The campaign ID", ) parser.add_argument( "-f", diff --git a/examples/feeds/create_feed_item_set.py b/examples/feeds/create_feed_item_set.py index c61fde4ba..06a5403d4 100644 --- a/examples/feeds/create_feed_item_set.py +++ b/examples/feeds/create_feed_item_set.py @@ -73,7 +73,7 @@ def main(client, customer_id, feed_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Creates a new feed item set for a specified feed." @@ -87,13 +87,19 @@ def main(client, customer_id, feed_id): help="The Google Ads customer ID.", ) parser.add_argument( - "-f", "--feed_id", type=str, required=True, help="The feed ID.", + "-f", + "--feed_id", + type=str, + required=True, + help="The feed ID.", ) args = parser.parse_args() try: main( - googleads_client, args.customer_id, args.feed_id, + googleads_client, + args.customer_id, + args.feed_id, ) except GoogleAdsException as ex: print( diff --git a/examples/feeds/get_feed_items_of_feed_item_set.py b/examples/feeds/get_feed_items_of_feed_item_set.py index 9e6b1f9bf..68d9abf76 100755 --- a/examples/feeds/get_feed_items_of_feed_item_set.py +++ b/examples/feeds/get_feed_items_of_feed_item_set.py @@ -66,7 +66,7 @@ def main(client, customer_id, feed_id, feed_item_set_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Gets all feed items of the specified feed item set." @@ -80,7 +80,11 @@ def main(client, customer_id, feed_id, feed_item_set_id): help="The Google Ads customer ID.", ) parser.add_argument( - "-i", "--feed_id", type=str, required=True, help="The Feed ID.", + "-i", + "--feed_id", + type=str, + required=True, + help="The Feed ID.", ) parser.add_argument( "-s", diff --git a/examples/feeds/link_feed_item_set.py b/examples/feeds/link_feed_item_set.py index 2e48ad30d..be4b25aa9 100644 --- a/examples/feeds/link_feed_item_set.py +++ b/examples/feeds/link_feed_item_set.py @@ -67,7 +67,7 @@ def main(client, customer_id, feed_id, feed_item_id, feed_item_set_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Links the specified feed item set to the specified feed item." @@ -81,7 +81,11 @@ def main(client, customer_id, feed_id, feed_item_id, feed_item_set_id): help="The Google Ads customer ID.", ) parser.add_argument( - "-f", "--feed_id", type=str, required=True, help="The feed ID.", + "-f", + "--feed_id", + type=str, + required=True, + help="The feed ID.", ) parser.add_argument( "-i", diff --git a/examples/feeds/remove_feed_items.py b/examples/feeds/remove_feed_items.py index cb7fb70d9..cc9be46d9 100755 --- a/examples/feeds/remove_feed_items.py +++ b/examples/feeds/remove_feed_items.py @@ -59,7 +59,7 @@ def main(client, customer_id, feed_id, feed_item_ids): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Removes feed items from a feed." diff --git a/examples/feeds/remove_flights_feed_item_attribute_value.py b/examples/feeds/remove_flights_feed_item_attribute_value.py index 714221166..f7682fa06 100644 --- a/examples/feeds/remove_flights_feed_item_attribute_value.py +++ b/examples/feeds/remove_flights_feed_item_attribute_value.py @@ -255,7 +255,7 @@ def get_feed_item(client, customer_id, feed_id, feed_item_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Removes a feed item attribute value of a feed item in a " diff --git a/examples/feeds/update_flights_feed_item_string_attribute_value.py b/examples/feeds/update_flights_feed_item_string_attribute_value.py index 54d29a7e9..3834dcc20 100755 --- a/examples/feeds/update_flights_feed_item_string_attribute_value.py +++ b/examples/feeds/update_flights_feed_item_string_attribute_value.py @@ -276,7 +276,7 @@ def get_attribute_index(target_feed_item_attribute_value, feed_item): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Updates a feed item attribute value in a flights feed." diff --git a/examples/misc/campaign_report_to_csv.py b/examples/misc/campaign_report_to_csv.py index c67ebd1ec..37465867f 100755 --- a/examples/misc/campaign_report_to_csv.py +++ b/examples/misc/campaign_report_to_csv.py @@ -108,7 +108,7 @@ def main(client, customer_id, output_file, write_headers): if __name__ == "__main__": # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. - google_ads_client = GoogleAdsClient.load_from_storage(version="v14") + google_ads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Retrieves a campaign stats and writes to CSV file." diff --git a/examples/misc/navigate_search_result_pages_caching_tokens.py b/examples/misc/navigate_search_result_pages_caching_tokens.py index 9f80ce007..c7d75a425 100755 --- a/examples/misc/navigate_search_result_pages_caching_tokens.py +++ b/examples/misc/navigate_search_result_pages_caching_tokens.py @@ -177,7 +177,7 @@ def cache_next_page_token(page_tokens, page, page_number): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( @@ -198,7 +198,8 @@ def cache_next_page_token(page_tokens, page, page_number): try: main( - googleads_client, args.customer_id, + googleads_client, + args.customer_id, ) except GoogleAdsException as ex: print( diff --git a/examples/misc/set_custom_client_timeouts.py b/examples/misc/set_custom_client_timeouts.py index 1c0ef09e3..f68219626 100755 --- a/examples/misc/set_custom_client_timeouts.py +++ b/examples/misc/set_custom_client_timeouts.py @@ -156,7 +156,7 @@ def make_unary_call(client, customer_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Demonstrates custom client timeouts in the context of " diff --git a/examples/misc/upload_image.py b/examples/misc/upload_image.py index 2e7e9995c..ba57ed0d5 100644 --- a/examples/misc/upload_image.py +++ b/examples/misc/upload_image.py @@ -12,7 +12,16 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""This code example uploads an image.""" +"""This code example uploads an image. + +This code example uses version v14 of the Google Ads API. Google Ads is +migrating from individual media files to assets, and version v15 of the API +removed support for MediaFileService as part of this migration. Once your Ads +account is migrated, this code example will stop working, and you should use +upload_image_asset.py instead. This code example will be removed once the +migration completes. For more details, see: +https://ads-developers.googleblog.com/2023/07/image-and-location-auto-migration.html +""" import argparse diff --git a/examples/misc/upload_image_asset.py b/examples/misc/upload_image_asset.py index 48f748513..2714bfbc4 100644 --- a/examples/misc/upload_image_asset.py +++ b/examples/misc/upload_image_asset.py @@ -63,7 +63,7 @@ def main(client, customer_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Upload an image asset from a URL." diff --git a/examples/misc/upload_media_bundle.py b/examples/misc/upload_media_bundle.py index 2922f7e8e..34872a2e2 100755 --- a/examples/misc/upload_media_bundle.py +++ b/examples/misc/upload_media_bundle.py @@ -12,7 +12,15 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""This example uploads an HTML5 zip file as a media bundle.""" +"""This example uploads an HTML5 zip file as a media bundle. + +This code example uses version v14 of the Google Ads API. Google Ads is +migrating from individual media files to assets, and version v15 of the API +removed support for MediaFileService as part of this migration. Once your Ads +account is migrated, this code example will stop working, and you should use +upload_image_asset.py instead. This code example will be removed once the +migration completes. For more details, see: +https://ads-developers.googleblog.com/2023/07/image-and-location-auto-migration.html""" import argparse diff --git a/examples/planning/forecast_reach.py b/examples/planning/forecast_reach.py index b850edc83..2580928de 100755 --- a/examples/planning/forecast_reach.py +++ b/examples/planning/forecast_reach.py @@ -205,7 +205,7 @@ def forecast_manual_mix( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Generates video ads reach forecast." diff --git a/examples/planning/generate_forecast_metrics.py b/examples/planning/generate_forecast_metrics.py index e4e13d649..a8b0c96ec 100755 --- a/examples/planning/generate_forecast_metrics.py +++ b/examples/planning/generate_forecast_metrics.py @@ -159,7 +159,7 @@ def generate_forecast_metrics(client, customer_id, campaign_to_forecast): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Generates forecast metrics for keyword planning." diff --git a/examples/planning/generate_historical_metrics.py b/examples/planning/generate_historical_metrics.py index 2c75dce99..2399dd67f 100755 --- a/examples/planning/generate_historical_metrics.py +++ b/examples/planning/generate_historical_metrics.py @@ -113,7 +113,7 @@ def generate_historical_metrics(client, customer_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Generates forecast metrics for keyword planning." diff --git a/examples/planning/generate_keyword_ideas.py b/examples/planning/generate_keyword_ideas.py index d187d8b23..b8da3a334 100755 --- a/examples/planning/generate_keyword_ideas.py +++ b/examples/planning/generate_keyword_ideas.py @@ -117,7 +117,7 @@ def map_locations_ids_to_resource_names(client, location_ids): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Generates keyword ideas from a list of seed keywords." 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 00b80190f..e0c516423 100755 --- a/examples/planning/get_ad_group_criterion_cpc_bid_simulations.py +++ b/examples/planning/get_ad_group_criterion_cpc_bid_simulations.py @@ -79,7 +79,7 @@ def main(client, customer_id, ad_group_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Gets all available ad group criterion CPC bid " diff --git a/examples/recommendations/apply_recommendation.py b/examples/recommendations/apply_recommendation.py index feb376966..4020dad73 100755 --- a/examples/recommendations/apply_recommendation.py +++ b/examples/recommendations/apply_recommendation.py @@ -33,8 +33,10 @@ def main(client, customer_id, recommendation_id): "ApplyRecommendationOperation" ) - apply_recommendation_operation.resource_name = recommendation_service.recommendation_path( - customer_id, recommendation_id + apply_recommendation_operation.resource_name = ( + recommendation_service.recommendation_path( + customer_id, recommendation_id + ) ) # This is where we override the recommended ad when a TextAdRecommendation is applied. @@ -56,7 +58,7 @@ def main(client, customer_id, recommendation_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Applies a specified recommendation.") diff --git a/examples/recommendations/detect_and_apply_recommendations.py b/examples/recommendations/detect_and_apply_recommendations.py index 1e5e0a6dd..ec7926666 100755 --- a/examples/recommendations/detect_and_apply_recommendations.py +++ b/examples/recommendations/detect_and_apply_recommendations.py @@ -68,17 +68,21 @@ def main(client, customer_id): "ApplyRecommendationOperation" ) - apply_recommendation_operation.resource_name = recommendation_service.recommendation_path( - customer_id, recommendation.id + apply_recommendation_operation.resource_name = ( + recommendation_service.recommendation_path( + customer_id, recommendation.id + ) ) apply_recommendation_operations.append( apply_recommendation_operation ) - recommendation_response = recommendation_service.apply_recommendation( - customer_id=customer_id, - operations=apply_recommendation_operations, + recommendation_response = ( + recommendation_service.apply_recommendation( + customer_id=customer_id, + operations=apply_recommendation_operations, + ) ) for resp in recommendation_response: @@ -99,7 +103,7 @@ def main(client, customer_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Detects and applies a specified recommendation.") diff --git a/examples/recommendations/dismiss_recommendation.py b/examples/recommendations/dismiss_recommendation.py index b7e52cb16..edd5869d1 100755 --- a/examples/recommendations/dismiss_recommendation.py +++ b/examples/recommendations/dismiss_recommendation.py @@ -46,7 +46,7 @@ def main(client, customer_id, recommendation_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Dismisses a recommendation with the given ID.") diff --git a/examples/recommendations/get_text_ad_recommendations.py b/examples/recommendations/get_text_ad_recommendations.py index 132ff6fea..33f5f4d06 100755 --- a/examples/recommendations/get_text_ad_recommendations.py +++ b/examples/recommendations/get_text_ad_recommendations.py @@ -65,7 +65,7 @@ def main(client, customer_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Lists TEXT_AD recommendations for specified customer." diff --git a/examples/remarketing/add_conversion_action.py b/examples/remarketing/add_conversion_action.py index 7f13c9cdb..b47b05dee 100755 --- a/examples/remarketing/add_conversion_action.py +++ b/examples/remarketing/add_conversion_action.py @@ -48,8 +48,11 @@ def main(client, customer_id): value_settings.always_use_default_value = True # Add the conversion action. - conversion_action_response = conversion_action_service.mutate_conversion_actions( - customer_id=customer_id, operations=[conversion_action_operation], + conversion_action_response = ( + conversion_action_service.mutate_conversion_actions( + customer_id=customer_id, + operations=[conversion_action_operation], + ) ) print( @@ -62,7 +65,7 @@ def main(client, customer_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds a conversion action for specified customer." diff --git a/examples/remarketing/add_conversion_based_user_list.py b/examples/remarketing/add_conversion_based_user_list.py index 8af058d7e..dff87d77a 100644 --- a/examples/remarketing/add_conversion_based_user_list.py +++ b/examples/remarketing/add_conversion_based_user_list.py @@ -47,8 +47,10 @@ def main(client, customer_id, conversion_action_ids): user_list_action_info_list = [] for conversion_action_id in conversion_action_ids: user_list_action_info = client.get_type("UserListActionInfo") - user_list_action_info.conversion_action = conversion_action_service.conversion_action_path( - customer_id, conversion_action_id + user_list_action_info.conversion_action = ( + conversion_action_service.conversion_action_path( + customer_id, conversion_action_id + ) ) user_list_action_info_list.append(user_list_action_info) @@ -78,7 +80,7 @@ def main(client, customer_id, conversion_action_ids): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Creates a basic user list based on conversion actions." diff --git a/examples/remarketing/add_custom_audience.py b/examples/remarketing/add_custom_audience.py index 2a9ad9cf6..9c7be0a02 100755 --- a/examples/remarketing/add_custom_audience.py +++ b/examples/remarketing/add_custom_audience.py @@ -124,7 +124,7 @@ def create_custom_audience_member(client, member_type, value): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds a custom audience for a specified customer." diff --git a/examples/remarketing/add_customer_match_user_list.py b/examples/remarketing/add_customer_match_user_list.py index 042a90307..9b88092cf 100755 --- a/examples/remarketing/add_customer_match_user_list.py +++ b/examples/remarketing/add_customer_match_user_list.py @@ -35,7 +35,15 @@ from google.ads.googleads.errors import GoogleAdsException -def main(client, customer_id, run_job, user_list_id, offline_user_data_job_id): +def main( + client, + customer_id, + run_job, + user_list_id, + offline_user_data_job_id, + ad_user_data_consent, + ad_personalization_consent, +): """Uses Customer Match to create and add users to a new user list. Args: @@ -47,6 +55,10 @@ def main(client, customer_id, run_job, user_list_id, offline_user_data_job_id): created. offline_user_data_job_id: ID of an existing OfflineUserDataJob in the PENDING state. If None, a new job is created. + ad_user_data_consent: The consent status for ad user data for all + members in the job. + ad_personalization_consent: The personalization consent status for ad + user data for all members in the job. """ googleads_service = client.get_service("GoogleAdsService") @@ -68,9 +80,11 @@ def main(client, customer_id, run_job, user_list_id, offline_user_data_job_id): user_list_resource_name, run_job, offline_user_data_job_id, + ad_user_data_consent, + ad_personalization_consent, ) - + # [START add_customer_match_user_list_3] def create_customer_match_user_list(client, customer_id): """Creates a Customer Match user list. @@ -126,6 +140,8 @@ def add_users_to_customer_match_user_list( user_list_resource_name, run_job, offline_user_data_job_id, + ad_user_data_consent, + ad_personalization_consent, ): """Uses Customer Match to create and add users to a new user list. @@ -138,6 +154,10 @@ def add_users_to_customer_match_user_list( Otherwise, only adds operations to the job. offline_user_data_job_id: ID of an existing OfflineUserDataJob in the PENDING state. If None, a new job is created. + ad_user_data_consent: The consent status for ad user data for all + members in the job. + ad_personalization_consent: The personalization consent status for ad + user data for all members in the job. """ # Creates the OfflineUserDataJobService client. offline_user_data_job_service_client = client.get_service( @@ -146,8 +166,10 @@ def add_users_to_customer_match_user_list( if offline_user_data_job_id: # Reuses the specified offline user data job. - offline_user_data_job_resource_name = offline_user_data_job_service_client.offline_user_data_job_path( - customer_id, offline_user_data_job_id + offline_user_data_job_resource_name = ( + offline_user_data_job_service_client.offline_user_data_job_path( + customer_id, offline_user_data_job_id + ) ) else: # Creates a new offline user data job. @@ -158,9 +180,24 @@ def add_users_to_customer_match_user_list( offline_user_data_job.customer_match_user_list_metadata.user_list = ( user_list_resource_name ) + + # Specifies whether user consent was obtained for the data you are + # uploading. For more details, see: + # https://www.google.com/about/company/user-consent-policy + if ad_user_data_consent: + offline_user_data_job.customer_match_user_list_metadata.consent.ad_user_data = client.enums.ConsentStatusEnum[ + ad_user_data_consent + ] + if ad_personalization_consent: + offline_user_data_job.customer_match_user_list_metadata.consent.ad_personalization = client.enums.ConsentStatusEnum[ + ad_personalization_consent + ] + # Issues a request to create an offline user data job. - create_offline_user_data_job_response = offline_user_data_job_service_client.create_offline_user_data_job( - customer_id=customer_id, job=offline_user_data_job + create_offline_user_data_job_response = ( + offline_user_data_job_service_client.create_offline_user_data_job( + customer_id=customer_id, job=offline_user_data_job + ) ) offline_user_data_job_resource_name = ( create_offline_user_data_job_response.resource_name @@ -497,7 +534,7 @@ def normalize_and_hash(s, remove_all_whitespace): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds a customer match user list for specified customer." @@ -540,6 +577,26 @@ def normalize_and_hash(s, remove_all_whitespace): "not specified, this example will create a new job." ), ) + parser.add_argument( + "-d", + "--ad_user_data_consent", + type=str, + choices=[e.name for e in googleads_client.enums.ConsentStatusEnum], + help=( + "The data consent status for ad user data for all members in " + "the job." + ), + ) + parser.add_argument( + "-p", + "--ad_personalization_consent", + type=str, + choices=[e.name for e in googleads_client.enums.ConsentStatusEnum], + help=( + "The personalization consent status for ad user data for all " + "members in the job." + ), + ) args = parser.parse_args() @@ -550,6 +607,8 @@ def normalize_and_hash(s, remove_all_whitespace): args.run_job, args.user_list_id, args.offline_user_data_job_id, + args.ad_user_data_consent, + args.ad_personalization_consent, ) except GoogleAdsException as ex: print( diff --git a/examples/remarketing/add_dynamic_remarketing_asset.py b/examples/remarketing/add_dynamic_remarketing_asset.py index 9344b5399..a308a7bf3 100755 --- a/examples/remarketing/add_dynamic_remarketing_asset.py +++ b/examples/remarketing/add_dynamic_remarketing_asset.py @@ -193,7 +193,7 @@ def link_asset_set_to_campaign( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds an asset for use in dynamic remarketing." diff --git a/examples/remarketing/add_flexible_rule_user_list.py b/examples/remarketing/add_flexible_rule_user_list.py index 0413e7cdc..f6b001e1b 100644 --- a/examples/remarketing/add_flexible_rule_user_list.py +++ b/examples/remarketing/add_flexible_rule_user_list.py @@ -152,7 +152,7 @@ def create_user_list_rule_info_from_url(client, url): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Creates a combination user list containing users that are " diff --git a/examples/remarketing/add_flights_feed.py b/examples/remarketing/add_flights_feed.py index 92e97b7d0..c2b03f143 100755 --- a/examples/remarketing/add_flights_feed.py +++ b/examples/remarketing/add_flights_feed.py @@ -413,7 +413,7 @@ def get_placeholder_fields_map(client, customer_id, feed_resource_name): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds a flights feed for specified customer." diff --git a/examples/remarketing/add_logical_user_list.py b/examples/remarketing/add_logical_user_list.py index 172cb8089..d0776ad86 100644 --- a/examples/remarketing/add_logical_user_list.py +++ b/examples/remarketing/add_logical_user_list.py @@ -45,8 +45,8 @@ def main(client, customer_id, user_list_ids): logical_user_list_operand_info = client.get_type( "LogicalUserListOperandInfo" ) - logical_user_list_operand_info.user_list = user_list_service.user_list_path( - customer_id, user_list_id + logical_user_list_operand_info.user_list = ( + user_list_service.user_list_path(customer_id, user_list_id) ) logical_user_list_operand_info_list.append( logical_user_list_operand_info @@ -86,7 +86,7 @@ def main(client, customer_id, user_list_ids): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Creates a combination user list containing users that are " diff --git a/examples/remarketing/add_merchant_center_dynamic_remarketing_campaign.py b/examples/remarketing/add_merchant_center_dynamic_remarketing_campaign.py index bf3b0e3eb..8ca3a6383 100644 --- a/examples/remarketing/add_merchant_center_dynamic_remarketing_campaign.py +++ b/examples/remarketing/add_merchant_center_dynamic_remarketing_campaign.py @@ -87,11 +87,6 @@ def create_campaign( campaign.shopping_setting.campaign_priority = 0 # This connects the campaign to the Merchant Center account. campaign.shopping_setting.merchant_id = merchant_center_account_id - # Display Network campaigns do not support partition by country. The only - # supported value is "ZZ". This signals that products from all countries are - # available in the campaign. The actual products which serve are based on - # the products tagged in the user list entry. - campaign.shopping_setting.sales_country = "ZZ" campaign.shopping_setting.enable_local = True # Dynamic remarketing campaigns are only available on the Google Display # Network. @@ -286,8 +281,10 @@ def attach_user_list(client, customer_id, ad_group_resource_name, user_list_id): ).user_list_path(customer_id, user_list_id) # Issue a mutate request to add the ad group criterion. - ad_group_criterion_response = ad_group_criterion_service.mutate_ad_group_criteria( - customer_id=customer_id, operations=[ad_group_criterion_operation] + ad_group_criterion_response = ( + ad_group_criterion_service.mutate_ad_group_criteria( + customer_id=customer_id, operations=[ad_group_criterion_operation] + ) ) print( "Created ad group criterion with resource name " @@ -299,7 +296,7 @@ def attach_user_list(client, customer_id, ad_group_resource_name, user_list_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/remarketing/add_real_estate_feed.py b/examples/remarketing/add_real_estate_feed.py index c282d9667..5d72f09a3 100644 --- a/examples/remarketing/add_real_estate_feed.py +++ b/examples/remarketing/add_real_estate_feed.py @@ -220,9 +220,9 @@ def create_feed_mapping( contextual_keywords_enum_value = placeholder_field_enum.CONTEXTUAL_KEYWORDS contextual_keywords_mapping = attribute_field_mapping() - contextual_keywords_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[ - contextual_keywords_enum_value - ].id + contextual_keywords_mapping.feed_attribute_id = ( + placeholders_to_feed_attribute_map[contextual_keywords_enum_value].id + ) contextual_keywords_mapping.real_estate_field = ( contextual_keywords_enum_value ) @@ -321,9 +321,9 @@ def create_feed_item( # Creates the contextual keywords feed attribute value. contextual_keywords_enum_value = placeholder_field_enum.CONTEXTUAL_KEYWORDS contextual_keywords_mapping = client.get_type("FeedItemAttributeValue") - contextual_keywords_mapping.feed_attribute_id = placeholders_to_feed_attribute_map[ - contextual_keywords_enum_value - ].id + contextual_keywords_mapping.feed_attribute_id = ( + placeholders_to_feed_attribute_map[contextual_keywords_enum_value].id + ) contextual_keywords_mapping.string_values.extend( ["beach community", "ocean view", "two bedroom"] ) @@ -434,7 +434,7 @@ def get_placeholder_fields_map(client, customer_id, feed_resource_name): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Adds a real estate feed for specified customer." diff --git a/examples/remarketing/set_up_advanced_remarketing.py b/examples/remarketing/set_up_advanced_remarketing.py index 3f5e53f76..e00d4bb1c 100644 --- a/examples/remarketing/set_up_advanced_remarketing.py +++ b/examples/remarketing/set_up_advanced_remarketing.py @@ -129,12 +129,18 @@ def main(client, customer_id): # [START setup_advanced_remarketing_2] checkout_and_cart_size_rule_group.rule_items.extend( - [checkout_rule, cart_size_rule,] + [ + checkout_rule, + cart_size_rule, + ] ) # [END setup_advanced_remarketing_2] # [START setup_advanced_remarketing_5] checkout_date_rule_group.rule_items.extend( - [start_date_rule, end_date_rule,] + [ + start_date_rule, + end_date_rule, + ] ) # [END setup_advanced_remarketing_5] @@ -156,7 +162,10 @@ def main(client, customer_id): # themselves will be ORed together. rule_operand = client.get_type("FlexibleRuleOperandInfo") rule_operand.rule.rule_item_groups.extend( - [checkout_and_cart_size_rule_group, checkout_date_rule_group,] + [ + checkout_and_cart_size_rule_group, + checkout_date_rule_group, + ] ) rule_operand.lookback_window_days = 7 flexible_rule_user_list_info.inclusive_operands.append(rule_operand) @@ -175,7 +184,7 @@ def main(client, customer_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Creates a rule-based user list defined by an expression " diff --git a/examples/remarketing/set_up_remarketing.py b/examples/remarketing/set_up_remarketing.py index fab7fade9..5110f1dbc 100755 --- a/examples/remarketing/set_up_remarketing.py +++ b/examples/remarketing/set_up_remarketing.py @@ -370,7 +370,7 @@ def modify_campaign_bids( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Demonstrates various operations involved in remarketing." diff --git a/examples/remarketing/update_audience_target_restriction.py b/examples/remarketing/update_audience_target_restriction.py index a7167106b..0ca4bda79 100644 --- a/examples/remarketing/update_audience_target_restriction.py +++ b/examples/remarketing/update_audience_target_restriction.py @@ -168,7 +168,7 @@ def update_targeting_setting( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Updates the audience target restriction of a given ad " diff --git a/examples/remarketing/upload_call_conversion.py b/examples/remarketing/upload_call_conversion.py index 86ac7b325..e9bca98b2 100644 --- a/examples/remarketing/upload_call_conversion.py +++ b/examples/remarketing/upload_call_conversion.py @@ -36,6 +36,7 @@ def main( conversion_value, conversion_custom_variable_id, conversion_custom_variable_value, + ad_user_data_consent, ): """Imports offline call conversion values for calls related to your ads. @@ -57,6 +58,8 @@ def main( variable to associate with the upload. conversion_custom_variable_value: The str value of the conversion custom variable to associate with the upload. + ad_user_data_consent: The consent status for ad user data for all + members in the job. """ # Get the ConversionUploadService client. conversion_upload_service = client.get_service("ConversionUploadService") @@ -80,13 +83,26 @@ def main( conversion_custom_variable.value = conversion_custom_variable_value call_conversion.custom_variables.append(conversion_custom_variable) + # Specifies whether user consent was obtained for the data you are + # uploading. For more details. see: + # https://www.google.com/about/company/user-consent-policy + if ad_user_data_consent: + call_conversion.consent.ad_user_data = client.enums.ConsentStatusEnum[ + ad_user_data_consent + ] + # Issue a request to upload the call conversion. + # Partial failure MUST be enabled for this request. request = client.get_type("UploadCallConversionsRequest") request.customer_id = customer_id request.conversions = [call_conversion] request.partial_failure = True - upload_call_conversions_response = conversion_upload_service.upload_call_conversions( - request=request + # NOTE: This request only uploads a single conversion, but if you have + # multiple conversions to upload, it's most efficient to upload them in a + # single request. See the following for per-request limits for reference: + # https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service + upload_call_conversions_response = ( + conversion_upload_service.upload_call_conversions(request=request) ) # Print any partial errors returned. @@ -112,7 +128,7 @@ def main( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Imports offline call conversion values for calls related " @@ -178,6 +194,16 @@ def main( type=str, help="The value of the conversion custom variable to associate with the upload.", ) + parser.add_argument( + "-d", + "--ad_user_data_consent", + type=str, + choices=[e.name for e in googleads_client.enums.ConsentStatusEnum], + help=( + "The data consent status for ad user data for all members in " + "the job." + ), + ) args = parser.parse_args() try: @@ -191,6 +217,7 @@ def main( args.conversion_value, args.conversion_custom_variable_id, args.conversion_custom_variable_value, + args.ad_user_data_consent, ) except GoogleAdsException as ex: print( diff --git a/examples/remarketing/upload_conversion_adjustment.py b/examples/remarketing/upload_conversion_adjustment.py index 6a45773b1..28d723bbf 100644 --- a/examples/remarketing/upload_conversion_adjustment.py +++ b/examples/remarketing/upload_conversion_adjustment.py @@ -46,8 +46,10 @@ def main( # The GCLID should have been uploaded before with a conversion conversion_adjustment = client.get_type("ConversionAdjustment") conversion_action_service = client.get_service("ConversionActionService") - conversion_adjustment.conversion_action = conversion_action_service.conversion_action_path( - customer_id, conversion_action_id + conversion_adjustment.conversion_action = ( + conversion_action_service.conversion_action_path( + customer_id, conversion_action_id + ) ) conversion_adjustment.adjustment_type = conversion_adjustment_type conversion_adjustment.adjustment_date_time = adjustment_date_time @@ -75,8 +77,10 @@ def main( request.customer_id = customer_id request.conversion_adjustments = [conversion_adjustment] request.partial_failure = True - response = conversion_adjustment_upload_service.upload_conversion_adjustments( - request=request, + response = ( + conversion_adjustment_upload_service.upload_conversion_adjustments( + request=request, + ) ) conversion_adjustment_result = response.results[0] print( @@ -92,7 +96,7 @@ def main( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Uploads a conversion adjustment." diff --git a/examples/remarketing/upload_conversion_with_identifiers.py b/examples/remarketing/upload_enhanced_conversions_for_leads.py similarity index 55% rename from examples/remarketing/upload_conversion_with_identifiers.py rename to examples/remarketing/upload_enhanced_conversions_for_leads.py index 3f61284fc..df5335fbb 100644 --- a/examples/remarketing/upload_conversion_with_identifiers.py +++ b/examples/remarketing/upload_enhanced_conversions_for_leads.py @@ -12,7 +12,13 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""Uploads a conversion using hashed email address instead of GCLID.""" +"""Uploads an enhanced conversion for leads by uploading a ClickConversion. + +The click conversion has hashed, first-party user-provided data from your +website lead forms. This includes user identifiers, and optionally, a click ID +and order ID. With this information, Google can tie the conversion to the ad +that drove the lead. +""" import argparse @@ -24,15 +30,15 @@ from google.ads.googleads.errors import GoogleAdsException -# [START upload_conversion_with_identifiers] def main( client, customer_id, conversion_action_id, - email_address, conversion_date_time, conversion_value, order_id, + gclid, + ad_user_data_consent, ): """The main method that creates all necessary entities for the example. @@ -40,73 +46,141 @@ def main( client: An initialized GoogleAdsClient instance. customer_id: The client customer ID string. conversion_action_id: The ID of the conversion action to upload to. - email_address: The email address for the conversion. conversion_date_time: The date and time of the conversion. conversion_value: The value of the conversion. order_id: The unique ID (transaction ID) of the conversion. + gclid: The Google click ID for the click. + ad_user_data_consent: The consent status for ad user data for all + members in the job. """ - # [START create_conversion] - conversion_action_service = client.get_service("ConversionActionService") - # Gets the conversion action resource name. - conversion_action_resource_name = conversion_action_service.conversion_action_path( - customer_id, conversion_action_id - ) - click_conversion = client.get_type("ClickConversion") - click_conversion.conversion_action = conversion_action_resource_name - click_conversion.conversion_date_time = conversion_date_time - click_conversion.conversion_value = conversion_value - click_conversion.currency_code = "USD" + # [START add_user_identifiers] + # Extract user email and phone from the raw data, normalize and hash it, + # then wrap it in UserIdentifier objects. Create a separate UserIdentifier + # object for each. The data in this example is hardcoded, but in your + # application you might read the raw data from an input file. - # Sets the order ID if provided. - if order_id: - click_conversion.order_id = order_id + # IMPORTANT: Since the identifier attribute of UserIdentifier + # (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier) + # is a oneof + # (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must + # set only ONE of hashed_email, hashed_phone_number, mobile_id, + # third_party_user_id, or address_info. Setting more than one of these + # attributes on the same UserIdentifier will clear all the other members of + # the oneof. For example, the following code is INCORRECT and will result in + # a UserIdentifier with ONLY a hashed_phone_number: + # + # incorrectly_populated_user_identifier = client.get_type("UserIdentifier") + # incorrectly_populated_user_identifier.hashed_email = "..."" + # incorrectly_populated_user_identifier.hashed_phone_number = "..."" + + raw_record = { + # Email address that includes a period (.) before the Gmail domain. + "email": "alex.2@example.com", + # Phone number to be converted to E.164 format, with a leading '+' as + # required. + "phone": "+1 800 5550102", + # This example lets you input conversion details as arguments, + # but in reality you might store this data alongside other user data, + # so we include it in this sample user record. + "order_id": order_id, + "gclid": gclid, + "conversion_action_id": conversion_action_id, + "conversion_date_time": conversion_date_time, + "conversion_value": conversion_value, + "currency_code": "USD", + "ad_user_data_consent": ad_user_data_consent, + } + # Constructs the click conversion. + click_conversion = client.get_type("ClickConversion") # Creates a user identifier using the hashed email address, using the - # normalize and hash method specifically for email addresses. If using a - # phone number, use the "_normalize_and_hash" method instead. - user_identifier = client.get_type("UserIdentifier") - # Creates a SHA256 hashed string using the given email address, as - # described at https://support.google.com/google-ads/answer/9888656. - user_identifier.hashed_email = normalize_and_hash_email_address( - email_address - ) + # normalize and hash method specifically for email addresses. + email_identifier = client.get_type("UserIdentifier") # Optional: Specifies the user identifier source. - user_identifier.user_identifier_source = ( + email_identifier.user_identifier_source = ( client.enums.UserIdentifierSourceEnum.FIRST_PARTY ) + # Uses the normalize and hash method specifically for email addresses. + email_identifier.hashed_phone_number = normalize_and_hash_email_address( + raw_record["email"] + ) # Adds the user identifier to the conversion. - click_conversion.user_identifiers.append(user_identifier) - # [END create_conversion] + click_conversion.user_identifiers.append(email_identifier) + + # Checks if the record has a phone number, and if so, adds a UserIdentifier + # for it. + if raw_record.get("phone") is not None: + phone_identifier = client.get_type("UserIdentifier") + phone_identifier.hashed_phone_number = normalize_and_hash( + raw_record["phone"] + ) + # Adds the phone identifier to the conversion adjustment. + click_conversion.user_identifiers.append(phone_identifier) + # [END add_user_identifiers] + + # [START add_conversion_details] + # Add details of the conversion. + # Gets the conversion action resource name. + conversion_action_service = client.get_service("ConversionActionService") + click_conversion.conversion_action = ( + conversion_action_service.conversion_action_path( + customer_id, raw_record["conversion_action_id"] + ) + ) + click_conversion.conversion_date_time = raw_record["conversion_date_time"] + click_conversion.conversion_value = raw_record["conversion_value"] + click_conversion.currency_code = raw_record["currency_code"] + # Sets the order ID if provided. + if raw_record.get("order_id"): + click_conversion.order_id = raw_record["order_id"] + + # Sets the gclid if provided. + if raw_record.get("gclid"): + click_conversion.gclid = raw_record["gclid"] + + # Specifies whether user consent was obtained for the data you are + # uploading. For more details, see: + # https://www.google.com/about/company/user-consent-policy + if raw_record["ad_user_data_consent"]: + click_conversion.consent.ad_user_data = client.enums.ConsentStatusEnum[ + raw_record["ad_user_data_consent"] + ] + # [END add_conversion_details] + + # [START upload_conversion] # Creates the conversion upload service client. conversion_upload_service = client.get_service("ConversionUploadService") # Uploads the click conversion. Partial failure should always be set to # True. + # NOTE: This request only uploads a single conversion, but if you have + # multiple conversions to upload, it's most efficient to upload them in a + # single request. See the following for per-request limits for reference: + # https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service response = conversion_upload_service.upload_click_conversions( customer_id=customer_id, conversions=[click_conversion], # Enables partial failure (must be true). partial_failure=True, ) + # [END upload_conversion] # Prints any partial errors returned. + # To review the overall health of your recent uploads, see: + # https://developers.google.com/google-ads/api/docs/conversions/upload-summaries if response.partial_failure_error: print( "Partial error encountered: " f"{response.partial_failure_error.message}" ) - - # Prints the result. - result = response.results[0] - # Only prints valid results. If the click conversion failed then this - # result will be returned as an empty message and will be falsy. - if result: + else: + # Prints the result. + result = response.results[0] print( "Uploaded conversion that occurred at " f"{result.conversion_data_time} " f"to {result.conversion_action}." ) - # [END upload_conversion_with_identifiers] # [START normalize_and_hash] @@ -159,7 +233,7 @@ def normalize_and_hash(s): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Imports offline call conversion values for calls related " @@ -180,13 +254,6 @@ def normalize_and_hash(s): required=True, help="The ID of the conversion action to upload to.", ) - parser.add_argument( - "-e", - "--email_address", - type=str, - required=True, - help="The email address for the conversion.", - ) parser.add_argument( "-d", "--conversion_date_time", @@ -209,6 +276,22 @@ def normalize_and_hash(s): type=str, help="the unique ID (transaction ID) of the conversion.", ) + parser.add_argument( + "-g", + "--gclid", + type=str, + help="the Google click ID (gclid) for the click.", + ) + parser.add_argument( + "-d", + "--ad_user_data_consent", + type=str, + choices=[e.name for e in googleads_client.enums.ConsentStatusEnum], + help=( + "The data consent status for ad user data for all members in " + "the job." + ), + ) args = parser.parse_args() try: @@ -216,10 +299,11 @@ def normalize_and_hash(s): googleads_client, args.customer_id, args.conversion_action_id, - args.email_address, args.conversion_date_time, args.conversion_value, args.order_id, + args.gclid, + args.ad_user_data_consent, ) except GoogleAdsException as ex: print( diff --git a/examples/remarketing/upload_conversion_enhancement.py b/examples/remarketing/upload_enhanced_conversions_for_web.py similarity index 55% rename from examples/remarketing/upload_conversion_enhancement.py rename to examples/remarketing/upload_enhanced_conversions_for_web.py index 191da3f24..ab0e2b808 100644 --- a/examples/remarketing/upload_conversion_enhancement.py +++ b/examples/remarketing/upload_enhanced_conversions_for_web.py @@ -12,7 +12,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""Uploads a conversion using hashed email address instead of GCLID.""" +"""Enhances a web conversion by uploading a ConversionAdjustment. + +The conversion adjustment contains hashed user identifiers and an order ID. +""" import argparse @@ -24,7 +27,6 @@ from google.ads.googleads.errors import GoogleAdsException -# [START upload_conversion_enhancement] def main( client, customer_id, @@ -43,47 +45,56 @@ def main( conversion_date_time: The date and time of the conversion. user_agent: The HTTP user agent of the conversion. """ - # [START create_adjustment] - conversion_action_service = client.get_service("ConversionActionService") + # [START add_user_identifiers] + # Extracts user email, phone, and address info from the raw data, normalizes + # and hashes it, then wraps it in UserIdentifier objects. Creates a separate + # UserIdentifier object for each. The data in this example is hardcoded, but + # in your application you might read the raw data from an input file. + + # IMPORTANT: Since the identifier attribute of UserIdentifier + # (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier) + # is a oneof + # (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must + # set only ONE of hashed_email, hashed_phone_number, mobile_id, + # third_party_user_id, or address_info. Setting more than one of these + # attributes on the same UserIdentifier will clear all the other members of + # the oneof. For example, the following code is INCORRECT and will result in + # a UserIdentifier with ONLY a hashed_phone_number: + # + # incorrectly_populated_user_identifier = client.get_type("UserIdentifier") + # incorrectly_populated_user_identifier.hashed_email = "..."" + # incorrectly_populated_user_identifier.hashed_phone_number = "..."" + + raw_record = { + # Email address that includes a period (.) before the Gmail domain. + "email": "alex.2@example.com", + # Address that includes all four required elements: first name, last + # name, country code, and postal code. + "first_name": "Alex", + "last_name": "Quinn", + "country_code": "US", + "postal_code": "94045", + # Phone number to be converted to E.164 format, with a leading '+' as + # required. + "phone": "+1 800 5550102", + # This example lets you input conversion details as arguments, but in + # reality you might store this data alongside other user data, so we + # include it in this sample user record. + "order_id": order_id, + "conversion_action_id": conversion_action_id, + "conversion_date_time": conversion_date_time, + "currency_code": "USD", + "user_agent": user_agent, + } + + # Constructs the enhancement adjustment. conversion_adjustment = client.get_type("ConversionAdjustment") - conversion_adjustment.conversion_action = conversion_action_service.conversion_action_path( - customer_id, conversion_action_id - ) conversion_adjustment.adjustment_type = ( client.enums.ConversionAdjustmentTypeEnum.ENHANCEMENT ) - # Enhancements MUST use order ID instead of GCLID date/time pair. - conversion_adjustment.order_id = order_id - - # Sets the conversion date and time if provided. Providing this value is - # optional but recommended. - if conversion_date_time: - conversion_adjustment.gclid_date_time_pair.conversion_date_time = ( - conversion_date_time - ) - - # Creates a user identifier using sample values for the user address, - # hashing where required. - address_identifier = client.get_type("UserIdentifier") - address_identifier.address_info.hashed_first_name = normalize_and_hash( - "Dana" - ) - address_identifier.address_info.hashed_last_name = normalize_and_hash( - "Quinn" - ) - address_identifier.address_info.hashed_street_address = normalize_and_hash( - "1600 Amphitheatre Pkwy" - ) - address_identifier.address_info.city = "Mountain View" - address_identifier.address_info.state = "CA" - address_identifier.address_info.postal_code = "94043" - address_identifier.address_info.country_code = "US" - # Optional: Specifies the user identifier source. - address_identifier.user_identifier_source = ( - client.enums.UserIdentifierSourceEnum.FIRST_PARTY - ) - # Creates a user identifier using the hashed email address. + # Creates a user identifier using the hashed email address, using the + # normalize and hash method specifically for email addresses. email_identifier = client.get_type("UserIdentifier") # Optional: Specifies the user identifier source. email_identifier.user_identifier_source = ( @@ -91,53 +102,121 @@ def main( ) # Uses the normalize and hash method specifically for email addresses. email_identifier.hashed_email = normalize_and_hash_email_address( - "dana@example.com" + raw_record["email"] ) + # Adds the email identifier to the conversion adjustment. + conversion_adjustment.user_identifiers.append(email_identifier) + + # Checks if the record has a phone number, and if so, adds a UserIdentifier + # for it. + if raw_record.get("phone") is not None: + phone_identifier = client.get_type("UserIdentifier") + phone_identifier.hashed_phone_number = normalize_and_hash( + raw_record["phone"] + ) + # Adds the phone identifier to the conversion adjustment. + conversion_adjustment.user_identifiers.append(phone_identifier) + + # Checks if the record has all the required mailing address elements, and if + # so, adds a UserIdentifier for the mailing address. + if raw_record.get("first_name") is not None: + # Checks if the record contains all the other required elements of a + # mailing address. + required_keys = ["last_name", "country_code", "postal_code"] + # Builds a new list of the required keys that are missing from + # raw_record. + missing_keys = [ + key for key in required_keys if key not in raw_record.keys() + ] + if len(missing_keys) > 0: + print( + "Skipping addition of mailing address information because the" + f"following required keys are missing: {missing_keys}" + ) + else: + # Creates a user identifier using sample values for the user address, + # hashing where required. + address_identifier = client.get_type("UserIdentifier") + address_info = address_identifier.address_info + address_info.hashed_first_name = normalize_and_hash( + raw_record["first_name"] + ) + address_info.hashed_last_name = normalize_and_hash( + raw_record["last_name"] + ) + address_info.hashed_street_address = normalize_and_hash( + raw_record["country_code"] + ) + address_info.hashed_street_address = normalize_and_hash( + raw_record["postal_code"] + ) + # Adds the address identifier to the conversion adjustment. + conversion_adjustment.user_identifiers.append(address_identifier) + # [END add_user_identifiers] - # Adds both user identifiers to the conversion adjustment. - conversion_adjustment.user_identifiers.extend( - [address_identifier, email_identifier] + # [START add_conversion_details] + conversion_action_service = client.get_service("ConversionActionService") + # Sets the conversion action. + conversion_adjustment.conversion_action = ( + conversion_action_service.conversion_action_path( + customer_id, raw_record["conversion_action_id"] + ) ) + # Sets the order ID. Enhancements MUST use order ID instead of GCLID + # date/time pair. + conversion_adjustment.order_id = order_id + + # Sets the conversion date and time if provided. Providing this value is + # optional but recommended. + if raw_record.get("conversion_date_time"): + conversion_adjustment.gclid_date_time_pair.conversion_date_time = ( + raw_record["conversion_date_time"] + ) + # Sets optional fields where a value was provided - if user_agent: + if raw_record.get("user_agent"): # Sets the user agent. 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. conversion_adjustment.user_agent = user_agent - # [END create_adjustment] + # [END add_conversion_details] + # [START upload_enhancement] # Creates the conversion adjustment upload service client. conversion_adjustment_upload_service = client.get_service( "ConversionAdjustmentUploadService" ) # Uploads the enhancement adjustment. Partial failure should always be set # to true. + # NOTE: This request only uploads a single conversion, but if you have + # multiple conversions to upload, it's still best to upload them in a single + # request. See the following for per-request limits for reference: + # https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service response = conversion_adjustment_upload_service.upload_conversion_adjustments( customer_id=customer_id, conversion_adjustments=[conversion_adjustment], # Enables partial failure (must be true). partial_failure=True, ) + # [END upload_enhancement] # Prints any partial errors returned. + # To review the overall health of your recent uploads, see: + # https://developers.google.com/google-ads/api/docs/conversions/upload-summaries if response.partial_failure_error: print( "Partial error encountered: " f"{response.partial_failure_error.message}" ) - - # Prints the result. - result = response.results[0] - # Only prints valid results. If the click conversion failed then this - # result will be returned as an empty message and will be falsy. - if result: + else: + # Prints the result. + result = response.results[0] print( f"Uploaded conversion adjustment of {result.conversion_action} for " f"order ID {result,order_id}." ) - # [END upload_conversion_enhancement] # [START normalize_and_hash] @@ -175,7 +254,7 @@ def normalize_and_hash(s): """Normalizes and hashes a string with SHA-256. Private customer data must be hashed during upload, as described at: - https://support.google.com/google-ads/answer/7474263 + https://support.google.com/google-ads/answer/9888656 Args: s: The string to perform this operation on. @@ -190,7 +269,7 @@ def normalize_and_hash(s): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Imports offline call conversion values for calls related " diff --git a/examples/remarketing/upload_offline_conversion.py b/examples/remarketing/upload_offline_conversion.py index 5b05d551a..8d15554eb 100644 --- a/examples/remarketing/upload_offline_conversion.py +++ b/examples/remarketing/upload_offline_conversion.py @@ -39,6 +39,7 @@ def main( conversion_custom_variable_value, gbraid, wbraid, + order_id, ): """Creates a click conversion with a default currency of USD. @@ -60,12 +61,15 @@ def main( wbraid parameters must be None. wbraid: The WBRAID for the iOS app conversion. If set, the gclid and gbraid parameters must be None. + order_id: The order ID for the click conversion. """ click_conversion = client.get_type("ClickConversion") conversion_upload_service = client.get_service("ConversionUploadService") conversion_action_service = client.get_service("ConversionActionService") - click_conversion.conversion_action = conversion_action_service.conversion_action_path( - customer_id, conversion_action_id + click_conversion.conversion_action = ( + conversion_action_service.conversion_action_path( + customer_id, conversion_action_id + ) ) # Sets the single specified ID field. @@ -82,18 +86,31 @@ def main( if conversion_custom_variable_id and conversion_custom_variable_value: conversion_custom_variable = client.get_type("CustomVariable") - conversion_custom_variable.conversion_custom_variable = conversion_upload_service.conversion_custom_variable_path( - customer_id, conversion_custom_variable_id + conversion_custom_variable.conversion_custom_variable = ( + conversion_upload_service.conversion_custom_variable_path( + customer_id, conversion_custom_variable_id + ) ) conversion_custom_variable.value = conversion_custom_variable_value click_conversion.custom_variables.append(conversion_custom_variable) + if order_id: + click_conversion.order_id = order_id + + # Uploads the click conversion. Partial failure must be set to True here. + # + # NOTE: This request only uploads a single conversion, but if you have + # multiple conversions to upload, it's most efficient to upload them in a + # single request. See the following for per-request limits for reference: + # https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_service request = client.get_type("UploadClickConversionsRequest") request.customer_id = customer_id request.conversions.append(click_conversion) request.partial_failure = True - conversion_upload_response = conversion_upload_service.upload_click_conversions( - request=request, + conversion_upload_response = ( + conversion_upload_service.upload_click_conversions( + request=request, + ) ) uploaded_click_conversion = conversion_upload_response.results[0] print( @@ -108,7 +125,7 @@ def main( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Uploads an offline conversion." @@ -186,7 +203,12 @@ def main( "example. See the following for more details: " "https://developers.google.com/google-ads/api/docs/conversions/upload-clicks", ) - + parser.add_argument( + "-o", + "--order_id", + type=str, + help="The order ID for the click conversion.", + ) args = parser.parse_args() try: @@ -201,6 +223,7 @@ def main( args.conversion_custom_variable_value, args.gbraid, args.wbraid, + args.order_id, ) except GoogleAdsException as ex: print( diff --git a/examples/remarketing/upload_store_sales_transactions.py b/examples/remarketing/upload_store_sales_transactions.py index 8b269bfe5..e83557fd0 100644 --- a/examples/remarketing/upload_store_sales_transactions.py +++ b/examples/remarketing/upload_store_sales_transactions.py @@ -43,6 +43,8 @@ def main( country_code, language_code, quantity, + ad_user_data_consent, + ad_personalization_consent, ): """Uploads offline conversion data for store sales transactions. @@ -83,6 +85,10 @@ def main( required if uploading with item attributes. quantity: Optional number of items sold. Only required if uploading with item attributes. + ad_user_data_consent: The consent status for ad user data for all + members in the job. + ad_personalization_consent: The personalization consent status for ad + user data for all members in the job. """ # Get the OfflineUserDataJobService and OperationService clients. offline_user_data_job_service = client.get_service( @@ -110,6 +116,13 @@ def main( offline_user_data_job_resource_name, conversion_action_id, custom_value, + item_id, + merchant_center_account_id, + country_code, + language_code, + quantity, + ad_user_data_consent, + ad_personalization_consent, ) # Issue an asynchronous request to run the offline user data job. @@ -230,8 +243,10 @@ def create_offline_user_data_job( # Set the third party partner ID uploading the transactions. store_sales_third_party_metadata.partner_id = partner_id - create_offline_user_data_job_response = offline_user_data_job_service.create_offline_user_data_job( - customer_id=customer_id, job=offline_user_data_job + create_offline_user_data_job_response = ( + offline_user_data_job_service.create_offline_user_data_job( + customer_id=customer_id, job=offline_user_data_job + ) ) offline_user_data_job_resource_name = ( create_offline_user_data_job_response.resource_name @@ -255,6 +270,8 @@ def add_transactions_to_offline_user_data_job( country_code, language_code, quantity, + ad_user_data_consent, + ad_personalization_consent, ): """Add operations to the job for a set of sample transactions. @@ -281,17 +298,24 @@ def add_transactions_to_offline_user_data_job( required if uploading with item attributes. quantity: Optional number of items sold. Only required if uploading with item attributes. + ad_user_data_consent: The consent status for ad user data for all + members in the job. + ad_personalization_consent: The personalization consent status for ad + user data for all members in the job. """ # Construct some sample transactions. operations = build_offline_user_data_job_operations( client, customer_id, conversion_action_id, + custom_value, item_id, merchant_center_account_id, country_code, language_code, quantity, + ad_user_data_consent, + ad_personalization_consent, ) # [START enable_warnings_1] @@ -304,8 +328,10 @@ def add_transactions_to_offline_user_data_job( request.enable_warnings = True request.operations = operations - response = offline_user_data_job_service.add_offline_user_data_job_operations( - request=request, + response = ( + offline_user_data_job_service.add_offline_user_data_job_operations( + request=request, + ) ) # [END enable_warnings_1] @@ -361,6 +387,8 @@ def build_offline_user_data_job_operations( country_code, language_code, quantity, + ad_user_data_consent, + ad_personalization_consent, ): """Create offline user data job operations for sample transactions. @@ -384,6 +412,10 @@ def build_offline_user_data_job_operations( required if uploading with item attributes. quantity: Optional number of items sold. Only required if uploading with item attributes. + ad_user_data_consent: The consent status for ad user data for all + members in the job. + ad_personalization_consent: The personalization consent status for ad + user data for all members in the job. Returns: A list of OfflineUserDataJobOperations. @@ -401,10 +433,10 @@ def build_offline_user_data_job_operations( user_data_with_email_address.user_identifiers.extend( [email_identifier, state_identifier] ) - user_data_with_email_address.transaction_attribute.conversion_action = client.get_service( - "ConversionActionService" - ).conversion_action_path( - customer_id, conversion_action_id + user_data_with_email_address.transaction_attribute.conversion_action = ( + client.get_service("ConversionActionService").conversion_action_path( + customer_id, conversion_action_id + ) ) user_data_with_email_address.transaction_attribute.currency_code = "USD" # Convert the transaction amount from $200 USD to micros. @@ -420,6 +452,23 @@ def build_offline_user_data_job_operations( datetime.now() - datetime.timedelta(months=1) ).strftime("%Y-%m-%d %H:%M:%S") + # Specifies whether user consent was obtained for the data you are + # uploading. For more details, see: + # https://www.google.com/about/company/user-consent-policy + if ad_user_data_consent: + user_data_with_email_address.consent.ad_user_data = ( + client.enums.ConsentStatusEnum[ad_user_data_consent] + ) + if ad_personalization_consent: + user_data_with_email_address.consent.ad_personalization = ( + client.enums.ConsentStatusEnum[ad_personalization_consent] + ) + + if custom_value: + user_data_with_email_address.transaction_attribute.custom_value = ( + custom_value + ) + # Create the second transaction for upload based on a physical address. user_data_with_physical_address_operation = client.get_type( "OfflineUserDataJobOperation" @@ -439,10 +488,10 @@ def build_offline_user_data_job_operations( address_identifier.address_info.country_code = "US" address_identifier.address_info.postal_code = "10011" user_data_with_physical_address.user_identifiers.append(address_identifier) - user_data_with_physical_address.transaction_attribute.conversion_action = client.get_service( - "ConversionActionService" - ).conversion_action_path( - customer_id, conversion_action_id + user_data_with_physical_address.transaction_attribute.conversion_action = ( + client.get_service("ConversionActionService").conversion_action_path( + customer_id, conversion_action_id + ) ) user_data_with_physical_address.transaction_attribute.currency_code = "EUR" # Convert the transaction amount from 450 EUR to micros. @@ -459,14 +508,6 @@ def build_offline_user_data_job_operations( "%Y-%m-%d %H:%M:%S" ) - if custom_value: - user_data_with_email_address.transaction_attribute.custom_value = ( - custom_value - ) - user_data_with_physical_address.transaction_attribute.custom_value = ( - custom_value - ) - # Optional: If uploading data with item attributes, also assign these # values in the transaction attribute if item_id: @@ -563,7 +604,7 @@ def check_job_status(client, customer_id, offline_user_data_job_resource_name): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="This example uploads offline data for store sales " @@ -584,21 +625,20 @@ def check_job_status(client, customer_id, offline_user_data_job_resource_name): required=True, help="The ID of a store sales conversion action.", ) - parser.add_argument( + group = parser.add_mutually_exclusive_group(required=False) + group.add_argument( "-k", "--custom_key", type=str, - required=False, help="Only required after creating a custom key and custom values in " "the account. Custom key and values are used to segment store sales " "conversions. This measurement can be used to provide more advanced " "insights. If provided, a custom value must also be provided", ) - parser.add_argument( + group.add_argument( "-v", "--custom_value", type=str, - required=False, help="Only required after creating a custom key and custom values in " "the account. Custom key and values are used to segment store sales " "conversions. This measurement can be used to provide more advanced " @@ -700,6 +740,26 @@ def check_job_status(client, customer_id, offline_user_data_job_resource_name): help="Optional number of items sold. Only required if uploading with " "item attributes.", ) + parser.add_argument( + "-d", + "--ad_user_data_consent", + type=str, + choices=[e.name for e in googleads_client.enums.ConsentStatusEnum], + help=( + "The data consent status for ad user data for all members in " + "the job." + ), + ) + parser.add_argument( + "-p", + "--ad_personalization_consent", + type=str, + choices=[e.name for e in googleads_client.enums.ConsentStatusEnum], + help=( + "The personalization consent status for ad user data for all " + "members in the job." + ), + ) args = parser.parse_args() # Additional check to make sure that custom_key and custom_value are either @@ -731,6 +791,8 @@ def check_job_status(client, customer_id, offline_user_data_job_resource_name): args.country_code, args.language_code, args.quantity, + args.ad_user_data_consent, + args.ad_personalization_consent, ) except GoogleAdsException as ex: print( diff --git a/examples/reporting/parallel_report_download.py b/examples/reporting/parallel_report_download.py index dab69b6fa..1308aa1b8 100644 --- a/examples/reporting/parallel_report_download.py +++ b/examples/reporting/parallel_report_download.py @@ -175,7 +175,7 @@ def generate_inputs(client, customer_ids, queries): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Download a set of reports in parallel from a list of " diff --git a/examples/shopping_ads/add_listing_scope.py b/examples/shopping_ads/add_listing_scope.py index 77f5c6b4c..026c59aad 100755 --- a/examples/shopping_ads/add_listing_scope.py +++ b/examples/shopping_ads/add_listing_scope.py @@ -79,8 +79,10 @@ def main(client, customer_id, campaign_id): campaign_criterion_service = client.get_service("CampaignCriterionService") - campaign_criterion_response = campaign_criterion_service.mutate_campaign_criteria( - customer_id=customer_id, operations=[campaign_criterion_operation] + campaign_criterion_response = ( + campaign_criterion_service.mutate_campaign_criteria( + customer_id=customer_id, operations=[campaign_criterion_operation] + ) ) print( @@ -94,7 +96,7 @@ def main(client, customer_id, campaign_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Adds a shopping listing scope to a shopping campaign.") 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 469b6bb05..32b50e2b8 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 @@ -189,11 +189,15 @@ def create_root(self): mutate_operation.asset_group_listing_group_filter_operation.create ) - asset_group_listing_group_filter.resource_name = googleads_service.asset_group_listing_group_filter_path( - self.customer_id, self.asset_group_id, self.root_listing_id + asset_group_listing_group_filter.resource_name = ( + googleads_service.asset_group_listing_group_filter_path( + self.customer_id, self.asset_group_id, self.root_listing_id + ) ) - asset_group_listing_group_filter.asset_group = googleads_service.asset_group_path( - self.customer_id, self.asset_group_id + asset_group_listing_group_filter.asset_group = ( + googleads_service.asset_group_path( + self.customer_id, self.asset_group_id + ) ) # Since this is the root node, do not set the # parent_listing_group_filter field. For all other nodes, this would @@ -208,9 +212,9 @@ def create_root(self): ) # Because this is a Performance Max campaign for retail, we need to - # specify that this is a shopping vertical. - asset_group_listing_group_filter.vertical = ( - self.client.enums.ListingGroupFilterVerticalEnum.SHOPPING + # specify that this is a shopping listing source. + asset_group_listing_group_filter.listing_source = ( + self.client.enums.ListingGroupFilterListingSourceEnum.SHOPPING ) return mutate_operation @@ -239,20 +243,30 @@ def create_subdivision(self, parent_id, temporary_id, dimension): mutate_operation.asset_group_listing_group_filter_operation.create ) - asset_group_listing_group_filter.resource_name = googleads_service.asset_group_listing_group_filter_path( - self.customer_id, self.asset_group_id, temporary_id + asset_group_listing_group_filter.resource_name = ( + googleads_service.asset_group_listing_group_filter_path( + self.customer_id, self.asset_group_id, temporary_id + ) ) - asset_group_listing_group_filter.asset_group = googleads_service.asset_group_path( - self.customer_id, self.asset_group_id + asset_group_listing_group_filter.asset_group = ( + googleads_service.asset_group_path( + self.customer_id, self.asset_group_id + ) ) - asset_group_listing_group_filter.parent_listing_group_filter = googleads_service.asset_group_listing_group_filter_path( - self.customer_id, self.asset_group_id, parent_id + asset_group_listing_group_filter.parent_listing_group_filter = ( + googleads_service.asset_group_listing_group_filter_path( + self.customer_id, self.asset_group_id, parent_id + ) ) + # We must use the Subdivision type to indicate that the + # AssetGroupListingGroupFilter will have children. asset_group_listing_group_filter.type_ = ( self.client.enums.ListingGroupFilterTypeEnum.SUBDIVISION ) - asset_group_listing_group_filter.vertical = ( - self.client.enums.ListingGroupFilterVerticalEnum.SHOPPING + # Because this is a Performance Max campaign for retail, we need to + # specify that this is in the shopping listing source. + asset_group_listing_group_filter.listing_source = ( + self.client.enums.ListingGroupFilterListingSourceEnum.SHOPPING ) asset_group_listing_group_filter.case_value = dimension @@ -281,14 +295,20 @@ def create_unit(self, parent_id, temporary_id, dimension): mutate_operation.asset_group_listing_group_filter_operation.create ) - asset_group_listing_group_filter.resource_name = googleads_service.asset_group_listing_group_filter_path( - self.customer_id, self.asset_group_id, temporary_id + asset_group_listing_group_filter.resource_name = ( + googleads_service.asset_group_listing_group_filter_path( + self.customer_id, self.asset_group_id, temporary_id + ) ) - asset_group_listing_group_filter.asset_group = googleads_service.asset_group_path( - self.customer_id, self.asset_group_id + asset_group_listing_group_filter.asset_group = ( + googleads_service.asset_group_path( + self.customer_id, self.asset_group_id + ) ) - asset_group_listing_group_filter.parent_listing_group_filter = googleads_service.asset_group_listing_group_filter_path( - self.customer_id, self.asset_group_id, parent_id + asset_group_listing_group_filter.parent_listing_group_filter = ( + googleads_service.asset_group_listing_group_filter_path( + self.customer_id, self.asset_group_id, parent_id + ) ) # We must use the UnitIncluded type to indicate that the # AssetGroupListingGroupFilter won't have children. @@ -296,9 +316,9 @@ def create_unit(self, parent_id, temporary_id, dimension): self.client.enums.ListingGroupFilterTypeEnum.UNIT_INCLUDED ) # Because this is a Performance Max campaign for retail, we need to - # specify that this is in the shopping vertical. - asset_group_listing_group_filter.vertical = ( - self.client.enums.ListingGroupFilterVerticalEnum.SHOPPING + # specify that this is in the shopping listing source. + asset_group_listing_group_filter.listing_source = ( + self.client.enums.ListingGroupFilterListingSourceEnum.SHOPPING ) asset_group_listing_group_filter.case_value = dimension @@ -325,20 +345,29 @@ def main(client, customer_id, asset_group_id, replace_existing_tree): if replace_existing_tree: # Retrieve a list of existing AssetGroupListingGroupFilters - existing_listing_group_filters = get_all_existing_listing_group_filter_assets_in_asset_group( - client, customer_id, asset_group_resource_name + existing_listing_group_filters = ( + get_all_existing_listing_group_filter_assets_in_asset_group( + client, customer_id, asset_group_resource_name + ) ) # If present, create MutateOperations to remove each # AssetGroupListingGroupFilter and add them to the list of operations. if existing_listing_group_filters: - remove_operation_factory = AssetGroupListingGroupFilterRemoveOperationFactory( - client, existing_listing_group_filters + remove_operation_factory = ( + AssetGroupListingGroupFilterRemoveOperationFactory( + client, existing_listing_group_filters + ) ) operations.extend(remove_operation_factory.remove_all()) - create_operation_factory = AssetGroupListingGroupFilterCreateOperationFactory( - client, customer_id, asset_group_id, _TEMPORARY_ID_LISTING_GROUP_ROOT, + create_operation_factory = ( + AssetGroupListingGroupFilterCreateOperationFactory( + client, + customer_id, + asset_group_id, + _TEMPORARY_ID_LISTING_GROUP_ROOT, + ) ) operations.append(create_operation_factory.create_root()) @@ -500,7 +529,7 @@ def print_response_details(mutate_operations, response): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/shopping_ads/add_performance_max_retail_campaign.py b/examples/shopping_ads/add_performance_max_retail_campaign.py index 5e5e78dd4..aaf996c3d 100644 --- a/examples/shopping_ads/add_performance_max_retail_campaign.py +++ b/examples/shopping_ads/add_performance_max_retail_campaign.py @@ -69,7 +69,6 @@ def main( client, customer_id, merchant_center_account_id, - sales_country, final_url, ): """The main method that creates all necessary entities for the example. @@ -78,7 +77,6 @@ def main( client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. merchant_center_account_id: The Merchant Center account ID. - sales_country: sales country of products to include in the campaign. final_url: the final URL. """ # [START add_performance_max_retail_campaign_1] @@ -131,7 +129,6 @@ def main( client, customer_id, merchant_center_account_id, - sales_country, ) ) campaign_criterion_operations = create_campaign_criterion_operations( @@ -223,7 +220,6 @@ def create_performance_max_campaign_operation( client, customer_id, merchant_center_account_id, - sales_country, ): """Creates a MutateOperation that creates a new Performance Max campaign. @@ -234,7 +230,6 @@ def create_performance_max_campaign_operation( client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. merchant_center_account_id: The Merchant Center account ID. - sales_country: Sales country of products to include in the campaign. Returns: a MutateOperation that creates a campaign. @@ -272,7 +267,13 @@ def create_performance_max_campaign_operation( # Set the shopping settings. campaign.shopping_setting.merchant_id = merchant_center_account_id - campaign.shopping_setting.sales_country = sales_country + + # Optional: To use products only from a specific feed, set + # shopping_setting.feed_label to the feed label used in Merchant Center. + # See: https://support.google.com/merchants/answer/12453549. + # Omitting the shopping_setting.feed_label field will use products from all + # feeds. + # campaign.shopping_setting.feed_label = "INSERT_FEED_LABEL_HERE" # Set the Final URL expansion opt out. This flag is specific to # Performance Max campaigns. If opted out (True), only the final URLs in @@ -475,9 +476,9 @@ def create_listing_group_filter_operation(client, customer_id): client.enums.ListingGroupFilterTypeEnum.UNIT_INCLUDED ) # Because this is a Performance Max campaign for retail, we need to specify - # that this is in the shopping vertical. - asset_group_listing_group.vertical = ( - client.enums.ListingGroupFilterVerticalEnum.SHOPPING + # that this is in the shopping listing source. + asset_group_listing_group.listing_source = ( + client.enums.ListingGroupFilterListingSourceEnum.SHOPPING ) return mutate_operation @@ -881,7 +882,7 @@ def print_response_details(response): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Creates a Performance Max retail campaign.") @@ -901,14 +902,6 @@ def print_response_details(response): required=True, help="The Merchant Center account ID.", ) - parser.add_argument( - "-f", - "--sales_country", - type=str, - required=False, - default="US", - help="The sales country of products to include in the campaign", - ) parser.add_argument( "-u", "--final_url", @@ -925,7 +918,6 @@ def print_response_details(response): googleads_client, args.customer_id, args.merchant_center_account_id, - args.sales_country, args.final_url, ) except GoogleAdsException as ex: diff --git a/examples/shopping_ads/add_shopping_product_ad.py b/examples/shopping_ads/add_shopping_product_ad.py index f71b024d2..7b61d98c7 100755 --- a/examples/shopping_ads/add_shopping_product_ad.py +++ b/examples/shopping_ads/add_shopping_product_ad.py @@ -174,9 +174,6 @@ def add_standard_shopping_campaign( ) campaign.shopping_setting.merchant_id = merchant_center_account_id - # Sets the sales country of products to include in the campaign. - campaign.shopping_setting.sales_country = "US" - # Sets the priority of the campaign. Higher numbers take priority over lower # numbers. For standard shopping campaigns, allowed values are between 0 and # 2, inclusive. @@ -239,8 +236,10 @@ def add_default_shopping_listing_group( # Set the bid for products in this listing group unit. ad_group_criterion.cpc_bid_micros = 500000 - ad_group_criterion_response = ad_group_criterion_service.mutate_ad_group_criteria( - customer_id=customer_id, operations=[ad_group_criterion_operation] + ad_group_criterion_response = ( + ad_group_criterion_service.mutate_ad_group_criteria( + customer_id=customer_id, operations=[ad_group_criterion_operation] + ) ) print( @@ -252,7 +251,7 @@ def add_default_shopping_listing_group( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( 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 61faf884f..d532fb1ad 100644 --- a/examples/shopping_ads/add_shopping_product_listing_group_tree.py +++ b/examples/shopping_ads/add_shopping_product_listing_group_tree.py @@ -183,7 +183,8 @@ def main(client, customer_id, ad_group_id, replace_existing_tree): # Biddable Unit node: (Brand other node) # * CPC bid: $0.05 client.copy_from( - brand_dimension_info.product_brand, client.get_type("ProductBrandInfo"), + brand_dimension_info.product_brand, + client.get_type("ProductBrandInfo"), ) operations.append( create_listing_group_unit_biddable( @@ -197,8 +198,10 @@ def main(client, customer_id, ad_group_id, replace_existing_tree): ) # Add the ad group criteria. - mutate_ad_group_criteria_response = ad_group_criterion_service.mutate_ad_group_criteria( - customer_id=customer_id, operations=operations + mutate_ad_group_criteria_response = ( + ad_group_criterion_service.mutate_ad_group_criteria( + customer_id=customer_id, operations=operations + ) ) # Print the results of the successful mutates. @@ -382,7 +385,7 @@ def create_listing_group_unit_biddable( if __name__ == "__main__": - googleads_client = GoogleAdsClient.load_from_storage(version="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Add shopping product listing group tree to a shopping ad " diff --git a/examples/shopping_ads/get_product_bidding_category_constant.py b/examples/shopping_ads/get_product_category_constants.py similarity index 66% rename from examples/shopping_ads/get_product_bidding_category_constant.py rename to examples/shopping_ads/get_product_category_constants.py index 1bdf213d2..bc2407ee8 100755 --- a/examples/shopping_ads/get_product_bidding_category_constant.py +++ b/examples/shopping_ads/get_product_category_constants.py @@ -12,7 +12,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""This example fetches the set of valid ProductBiddingCategories.""" +"""This example fetches the set of all ProductCategoryConstants.""" import argparse @@ -32,18 +32,22 @@ def display_categories(categories, prefix=""): Returns: None """ for category in categories: - print(f"{prefix}{category.name} [{category.category_id}]") - if not category.children: - display_categories(category.children, prefix=prefix + category.name) + print(f"{prefix} {category.localized_name} [{category.resource_name}]") + if category.children: + display_categories( + category.children, prefix=f"{prefix} {category.localized_name}" + ) def main(client, customer_id): """Fetches the set of valid ProductBiddingCategories.""" class Category: - def __init__(self, name=None, category_id=None, children=None): - self.name = name - self.category_id = category_id + def __init__( + self, localized_name=None, resource_name=None, children=None + ): + self.localized_name = localized_name + self.resource_name = resource_name if children is None: self.children = [] else: @@ -51,10 +55,10 @@ def __init__(self, name=None, category_id=None, children=None): ga_service = client.get_service("GoogleAdsService") query = """ - SELECT product_bidding_category_constant.localized_name, - product_bidding_category_constant.product_bidding_category_constant_parent - FROM product_bidding_category_constant WHERE - product_bidding_category_constant.country_code IN ("US")""" + SELECT + product_category_constant.localizations, + product_category_constant.product_category_constant_parent + FROM product_category_constant""" search_request = client.get_type("SearchGoogleAdsStreamRequest") search_request.customer_id = customer_id @@ -68,24 +72,33 @@ def __init__(self, name=None, category_id=None, children=None): for batch in stream: for row in batch.results: - product_bidding_category = row.product_bidding_category_constant + # Gets the product category constant from the row. + product_category = row.product_category_constant + + localized_name = "" + for localization in product_category.localizations: + region = localization.region_code + lang = localization.language_code + if region == "US" and lang == "en": + # Gets the name from the product category localization. + localized_name = localization.value + break category = Category( - product_bidding_category.localized_name, - product_bidding_category.resource_name, + localized_name=localized_name, + resource_name=product_category.resource_name, ) - all_categories[category.category_id] = category - parent = ( - product_bidding_category.product_bidding_category_constant_parent + all_categories[category.resource_name] = category + parent_resource_name = ( + product_category.product_category_constant_parent ) - parent_id = getattr(parent, "value", None) # Links the category to the parent category if any. - if parent_id: + if parent_resource_name: # Adds the category as a child category of the parent # category. - all_categories[parent_id].children.append(category) + all_categories[parent_resource_name].children.append(category) else: # Otherwise adds the category as a root category. root_categories.append(category) @@ -94,7 +107,7 @@ def __init__(self, name=None, category_id=None, children=None): if __name__ == "__main__": - googleads_client = GoogleAdsClient.load_from_storage(version="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Get Product Bidding Category Constant" diff --git a/examples/targeting/add_campaign_targeting_criteria.py b/examples/targeting/add_campaign_targeting_criteria.py index 778724da7..4df8c57b4 100755 --- a/examples/targeting/add_campaign_targeting_criteria.py +++ b/examples/targeting/add_campaign_targeting_criteria.py @@ -33,8 +33,10 @@ def main(client, customer_id, campaign_id, keyword_text, location_id): create_proximity_op(client, customer_id, campaign_id), ] - campaign_criterion_response = campaign_criterion_service.mutate_campaign_criteria( - customer_id=customer_id, operations=operations + campaign_criterion_response = ( + campaign_criterion_service.mutate_campaign_criteria( + customer_id=customer_id, operations=operations + ) ) for result in campaign_criterion_response.results: @@ -57,8 +59,8 @@ def create_location_op(client, customer_id, campaign_id, location_id): # GeoTargetConstantService.suggest_geo_target_constants() and directly # apply GeoTargetConstant.resource_name here. An example can be found # in get_geo_target_constant_by_names.py. - campaign_criterion.location.geo_target_constant = geo_target_constant_service.geo_target_constant_path( - location_id + campaign_criterion.location.geo_target_constant = ( + geo_target_constant_service.geo_target_constant_path(location_id) ) return campaign_criterion_operation @@ -109,7 +111,7 @@ def create_proximity_op(client, customer_id, campaign_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/targeting/add_customer_negative_criteria.py b/examples/targeting/add_customer_negative_criteria.py index 8799fb2fd..e3fbd222d 100755 --- a/examples/targeting/add_customer_negative_criteria.py +++ b/examples/targeting/add_customer_negative_criteria.py @@ -53,9 +53,11 @@ def main(client, customer_id): ) # Issues a mutate request to add the negative customer criteria. - response = customer_negative_criterion_service.mutate_customer_negative_criteria( - customer_id=customer_id, - operations=[tragedy_criterion_op, placement_criterion_op], + response = ( + customer_negative_criterion_service.mutate_customer_negative_criteria( + customer_id=customer_id, + operations=[tragedy_criterion_op, placement_criterion_op], + ) ) print(f"Added {len(response.results)} negative customer criteria:") for negative_criterion in response.results: @@ -65,7 +67,7 @@ def main(client, customer_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( @@ -86,7 +88,8 @@ def main(client, customer_id): try: main( - googleads_client, args.customer_id, + googleads_client, + args.customer_id, ) except GoogleAdsException as ex: print( diff --git a/examples/targeting/add_demographic_targeting_criteria.py b/examples/targeting/add_demographic_targeting_criteria.py index 9faf3b253..392ac4c7a 100755 --- a/examples/targeting/add_demographic_targeting_criteria.py +++ b/examples/targeting/add_demographic_targeting_criteria.py @@ -51,12 +51,14 @@ def main(client, customer_id, ad_group_id): ) # Add two ad group criteria - ad_group_criterion_response = ad_group_criterion_service.mutate_ad_group_criteria( - customer_id=customer_id, - operations=[ - gender_ad_group_criterion_operation, - age_range_ad_group_criterion_operation, - ], + ad_group_criterion_response = ( + ad_group_criterion_service.mutate_ad_group_criteria( + customer_id=customer_id, + operations=[ + gender_ad_group_criterion_operation, + age_range_ad_group_criterion_operation, + ], + ) ) for result in ad_group_criterion_response.results: @@ -66,7 +68,7 @@ def main(client, customer_id, ad_group_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/targeting/get_geo_target_constants_by_names.py b/examples/targeting/get_geo_target_constants_by_names.py index a7765b197..bacbfb720 100755 --- a/examples/targeting/get_geo_target_constants_by_names.py +++ b/examples/targeting/get_geo_target_constants_by_names.py @@ -64,7 +64,7 @@ def main(client): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") try: main(googleads_client) diff --git a/examples/travel/add_hotel_ad.py b/examples/travel/add_hotel_ad.py index f4845d866..a1f764a72 100755 --- a/examples/travel/add_hotel_ad.py +++ b/examples/travel/add_hotel_ad.py @@ -187,7 +187,7 @@ def add_hotel_campaign( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/examples/travel/add_hotel_ad_group_bid_modifiers.py b/examples/travel/add_hotel_ad_group_bid_modifiers.py index 5ace7159d..1990ad7f3 100755 --- a/examples/travel/add_hotel_ad_group_bid_modifiers.py +++ b/examples/travel/add_hotel_ad_group_bid_modifiers.py @@ -72,7 +72,7 @@ def main(client, customer_id, ad_group_id): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Adds an ad group bid modifier to a hotel ad group.") diff --git a/examples/travel/add_hotel_listing_group_tree.py b/examples/travel/add_hotel_listing_group_tree.py index 400f0e622..dacbf74fc 100755 --- a/examples/travel/add_hotel_listing_group_tree.py +++ b/examples/travel/add_hotel_listing_group_tree.py @@ -97,8 +97,10 @@ def main(client, customer_id, ad_group_id, percent_cpc_bid_micro_amount): ) # Adds the listing group and prints the resulting node resource names. - mutate_ad_group_criteria_response = ad_group_criterion_service.mutate_ad_group_criteria( - customer_id=customer_id, operations=operations + mutate_ad_group_criteria_response = ( + ad_group_criterion_service.mutate_ad_group_criteria( + customer_id=customer_id, operations=operations + ) ) results = mutate_ad_group_criteria_response.results print( @@ -132,7 +134,8 @@ def add_root_node( # Create the root of the tree as a SUBDIVISION node. root_listing_group_info = create_listing_group_info( - client, client.enums.ListingGroupTypeEnum.SUBDIVISION, + client, + client.enums.ListingGroupTypeEnum.SUBDIVISION, ) root_ad_group_criterion = create_ad_group_criterion( @@ -456,7 +459,7 @@ def create_ad_group_criterion( 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description="Shows how to add a hotel listing group tree with two " 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 a8aa9e521..a5d618d45 100644 --- a/examples/travel/add_performance_max_for_travel_goals_campaign.py +++ b/examples/travel/add_performance_max_for_travel_goals_campaign.py @@ -616,7 +616,9 @@ def create_asset_group_operations( # and link it to the asset group. asset_mutate_operation = client.get_type("MutateOperation") asset = asset_mutate_operation.asset_operation.create - asset.resource_name = googleads_service.asset_path(customer_id, next_temp_id) + asset.resource_name = googleads_service.asset_path( + customer_id, next_temp_id + ) asset.name = ( f"Suggested call-to-action asset #{get_printable_datetime()}" ) @@ -629,7 +631,9 @@ def create_asset_group_operations( asset_group_asset = ( asset_group_asset_mutate_operation.asset_group_asset_operation.create ) - asset_group_asset.asset = googleads_service.asset_path(customer_id, next_temp_id) + asset_group_asset.asset = googleads_service.asset_path( + customer_id, next_temp_id + ) asset_group_asset.asset_group = asset_group_resource_name asset_group_asset.field_type = ( client.enums.AssetFieldTypeEnum.CALL_TO_ACTION_SELECTION @@ -808,7 +812,6 @@ def create_image_assets_for_asset_group( if field_type_enum.name in required_image_asset_counts: required_image_asset_counts[field_type_enum.name] += 1 - # Adds more image assets to fulfill the requirements. for field_type_name, min_count in MIN_REQUIRED_IMAGE_ASSET_COUNTS.items(): difference = min_count - required_image_asset_counts[field_type_name] @@ -928,7 +931,7 @@ def print_response_details(mutate_response): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=("Creates a Performance Max for travel goals campaign.") diff --git a/examples/travel/add_things_to_do_ad.py b/examples/travel/add_things_to_do_ad.py index 119797ef2..b074801bf 100755 --- a/examples/travel/add_things_to_do_ad.py +++ b/examples/travel/add_things_to_do_ad.py @@ -228,7 +228,7 @@ def add_ad_group_ad(client, customer_id, ad_group_resource_name): 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="v14") + googleads_client = GoogleAdsClient.load_from_storage(version="v15") parser = argparse.ArgumentParser( description=( diff --git a/google-ads.yaml b/google-ads.yaml index 2ca61ee72..8a3129346 100644 --- a/google-ads.yaml +++ b/google-ads.yaml @@ -34,7 +34,9 @@ refresh_token: INSERT_REFRESH_TOKEN_HERE # "json_key_file_path" value should be a path to your local private key json file, and # # "impersonated_email" should be the email address that is being used to impersonate the # # credentials making requests. for more information on service accounts, see: # -# https://developers.google.com/google-ads/api/docs/oauth/service-accounts # +# https://developers.google.com/google-ads/api/docs/oauth/service-accounts. # +# If you're authorizing with direct account access, then the "impersonated_email" # +# configuration is optional. # ########################################################################################## # json_key_file_path: INSERT_PATH_TO_JSON_KEY_FILE_HERE # impersonated_email: INSERT_DOMAIN_WIDE_DELEGATION_ACCOUNT diff --git a/google/ads/googleads/__init__.py b/google/ads/googleads/__init__.py index afc8072d7..6002fd556 100644 --- a/google/ads/googleads/__init__.py +++ b/google/ads/googleads/__init__.py @@ -19,12 +19,12 @@ import google.ads.googleads.errors import google.ads.googleads.util -VERSION = "22.0.0" +VERSION = "22.1.0" # Checks if the current runtime is Python 3.7. -if sys.version_info.major == 3 and sys.version_info.minor == 7: +if sys.version_info.major == 3 and sys.version_info.minor <= 7: warnings.warn( - "Python 3.7 is deprecated in the google-ads package. Please upgrade to " - "Python 3.8 or higher.", - category=DeprecationWarning - ) \ No newline at end of file + "Python versions less than 3.7 are deprecated in the google-ads " + "package. Please upgrade to Python 3.8 or higher.", + category=DeprecationWarning, + ) diff --git a/google/ads/googleads/client.py b/google/ads/googleads/client.py index 65ac915a5..650cf0825 100644 --- a/google/ads/googleads/client.py +++ b/google/ads/googleads/client.py @@ -33,7 +33,7 @@ _SERVICE_CLIENT_TEMPLATE = "{}Client" -_VALID_API_VERSIONS = ["v14", "v13"] +_VALID_API_VERSIONS = ["v15", "v14", "v13"] _DEFAULT_VERSION = _VALID_API_VERSIONS[0] # Retrieve the version of this client library to be sent in the user-agent @@ -187,6 +187,9 @@ def _get_client_kwargs(cls, config_data): "linked_customer_id": config_data.get("linked_customer_id"), "http_proxy": config_data.get("http_proxy"), "use_proto_plus": config_data.get("use_proto_plus"), + "use_cloud_org_for_api_access": config_data.get( + "use_cloud_org_for_api_access" + ), } @classmethod @@ -302,6 +305,7 @@ def __init__( version=None, http_proxy=None, use_proto_plus=False, + use_cloud_org_for_api_access=None, ): """Initializer for the GoogleAdsClient. @@ -314,6 +318,13 @@ def __init__( linked_customer_id: a str specifying a linked customer ID. version: a str indicating the Google Ads API version to be used. http_proxy: a str specifying the proxy URI through which to connect. + use_proto_plus: a bool specifying whether or not to use proto-plus + for protobuf message interfaces. + use_cloud_org_for_api_access: a str specifying whether to use the + Google Cloud Organization of your Google Cloud project instead + of developer token to determine your Google Ads API access + levels. Use this flag only if you are enrolled into a limited + pilot that supports this configuration """ if logging_config: logging.config.dictConfig(logging_config) @@ -326,6 +337,7 @@ def __init__( self.version = version self.http_proxy = http_proxy self.use_proto_plus = use_proto_plus + self.use_cloud_org_for_api_access = use_cloud_org_for_api_access self.enums = _EnumGetter(self) # If given, write the http_proxy channel option for GRPC to use @@ -386,6 +398,7 @@ def get_service(self, name, version=_DEFAULT_VERSION, interceptors=None): self.developer_token, self.login_customer_id, self.linked_customer_id, + self.use_cloud_org_for_api_access, ), LoggingInterceptor(_logger, version, endpoint), ExceptionInterceptor(version, use_proto_plus=self.use_proto_plus), diff --git a/google/ads/googleads/config.py b/google/ads/googleads/config.py index 890f0e68c..3b2c9fcef 100644 --- a/google/ads/googleads/config.py +++ b/google/ads/googleads/config.py @@ -33,10 +33,12 @@ "logging", "linked_customer_id", "http_proxy", + "use_cloud_org_for_api_access", ) _CONFIG_FILE_PATH_KEY = ("configuration_file_path",) _OAUTH2_INSTALLED_APP_KEYS = ("client_id", "client_secret", "refresh_token") -_OAUTH2_SERVICE_ACCOUNT_KEYS = ("json_key_file_path", "impersonated_email") +_OAUTH2_REQUIRED_SERVICE_ACCOUNT_KEYS = ("json_key_file_path",) +_OAUTH2_OPTIONAL_SERVICE_ACCOUNT_KEYS = ("impersonated_email",) # These keys are deprecated environment variables that can be used in place of # the primary OAuth2 service account keys for backwards compatibility. They will # be removed in favor of the primary keys at some point. @@ -50,7 +52,8 @@ + _OPTIONAL_KEYS + _OAUTH2_INSTALLED_APP_KEYS + _CONFIG_FILE_PATH_KEY - + _OAUTH2_SERVICE_ACCOUNT_KEYS + + _OAUTH2_REQUIRED_SERVICE_ACCOUNT_KEYS + + _OAUTH2_OPTIONAL_SERVICE_ACCOUNT_KEYS + _SECONDARY_OAUTH2_SERVICE_ACCOUNT_KEYS } @@ -350,13 +353,13 @@ def get_oauth2_installed_app_keys(): return _OAUTH2_INSTALLED_APP_KEYS -def get_oauth2_service_account_keys(): +def get_oauth2_required_service_account_keys(): """A getter that returns the required OAuth2 service account keys. Returns: A tuple containing the required keys as strs. """ - return _OAUTH2_SERVICE_ACCOUNT_KEYS + return _OAUTH2_REQUIRED_SERVICE_ACCOUNT_KEYS def convert_login_customer_id_to_str(config_data): diff --git a/google/ads/googleads/interceptors/helpers.py b/google/ads/googleads/interceptors/helpers.py index e1e0da0ae..61e99f089 100644 --- a/google/ads/googleads/interceptors/helpers.py +++ b/google/ads/googleads/interceptors/helpers.py @@ -39,6 +39,12 @@ "ChangeEvent": ["user_email"], "CreateCustomerClientRequest": ["email_address"], "Feed": ["places_location_feed_data.email_address"], + "LocalServicesLead": [ + "contact_details.phone_number", + "contact_details.email", + "contact_details.consumer_name", + ], + "LocalServicesLeadConversation": ["message_details.text"], } # This is a list of the names of messages that return search results from the diff --git a/google/ads/googleads/interceptors/metadata_interceptor.py b/google/ads/googleads/interceptors/metadata_interceptor.py index 00787df60..1f8ea32a4 100644 --- a/google/ads/googleads/interceptors/metadata_interceptor.py +++ b/google/ads/googleads/interceptors/metadata_interceptor.py @@ -51,7 +51,11 @@ class MetadataInterceptor( """An interceptor that appends custom metadata to requests.""" def __init__( - self, developer_token, login_customer_id, linked_customer_id=None + self, + developer_token, + login_customer_id, + linked_customer_id=None, + use_cloud_org_for_api_access=None, ): """Initialization method for this class. @@ -59,6 +63,11 @@ def __init__( developer_token: a str developer token. login_customer_id: a str specifying a login customer ID. linked_customer_id: a str specifying a linked customer ID. + use_cloud_org_for_api_access: a str specifying whether to use the + Google Cloud Organization of your Google Cloud project instead + of developer token to determine your Google Ads API access + levels. Use this flag only if you are enrolled into a limited + pilot that supports this configuration """ self.developer_token_meta = ("developer-token", developer_token) self.login_customer_id_meta = ( @@ -71,6 +80,7 @@ def __init__( if linked_customer_id else None ) + self.use_cloud_org_for_api_access = use_cloud_org_for_api_access def _update_client_call_details_metadata( self, client_call_details, metadata @@ -112,7 +122,10 @@ def _intercept(self, continuation, client_call_details, request): else: metadata = list(client_call_details.metadata) - metadata.append(self.developer_token_meta) + # If self.use_cloud_org_for_api_access is not True, add the developer + # token to the request's metadata + if not self.use_cloud_org_for_api_access: + metadata.append(self.developer_token_meta) if self.login_customer_id_meta: metadata.append(self.login_customer_id_meta) diff --git a/google/ads/googleads/oauth2.py b/google/ads/googleads/oauth2.py index 9bda378c9..0ed119f2e 100644 --- a/google/ads/googleads/oauth2.py +++ b/google/ads/googleads/oauth2.py @@ -107,7 +107,9 @@ def get_credentials(config_data): An initialized credentials instance. """ required_installed_app_keys = config.get_oauth2_installed_app_keys() - required_service_account_keys = config.get_oauth2_service_account_keys() + required_service_account_keys = ( + config.get_oauth2_required_service_account_keys() + ) if all(key in config_data for key in required_installed_app_keys): # Using the Installed App Flow diff --git a/google/ads/googleads/v15/__init__.py b/google/ads/googleads/v15/__init__.py new file mode 100644 index 000000000..9c4c0e19f --- /dev/null +++ b/google/ads/googleads/v15/__init__.py @@ -0,0 +1,1947 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import importlib +import sys + + +if sys.version_info < (3, 7): + raise ImportError("This module requires Python 3.7 or later.") + + +_lazy_type_to_package_map = { + # Message types + "ActivityCountryInfo": "google.ads.googleads.v15.common.types.criteria", + "ActivityIdInfo": "google.ads.googleads.v15.common.types.criteria", + "ActivityRatingInfo": "google.ads.googleads.v15.common.types.criteria", + "AdAssetPolicySummary": "google.ads.googleads.v15.common.types.asset_policy", + "AdCallToActionAsset": "google.ads.googleads.v15.common.types.ad_asset", + "AdDiscoveryCarouselCardAsset": "google.ads.googleads.v15.common.types.ad_asset", + "AddressInfo": "google.ads.googleads.v15.common.types.criteria", + "AdImageAsset": "google.ads.googleads.v15.common.types.ad_asset", + "AdMediaBundleAsset": "google.ads.googleads.v15.common.types.ad_asset", + "AdScheduleInfo": "google.ads.googleads.v15.common.types.criteria", + "AdTextAsset": "google.ads.googleads.v15.common.types.ad_asset", + "AdVideoAsset": "google.ads.googleads.v15.common.types.ad_asset", + "AffiliateLocationFeedItem": "google.ads.googleads.v15.common.types.extensions", + "AgeDimension": "google.ads.googleads.v15.common.types.audiences", + "AgeRangeInfo": "google.ads.googleads.v15.common.types.criteria", + "AgeSegment": "google.ads.googleads.v15.common.types.audiences", + "AppAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "AppEngagementAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "AppFeedItem": "google.ads.googleads.v15.common.types.extensions", + "AppPaymentModelInfo": "google.ads.googleads.v15.common.types.criteria", + "AppPreRegistrationAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "AssetDisapproved": "google.ads.googleads.v15.common.types.asset_policy", + "AssetInteractionTarget": "google.ads.googleads.v15.common.types.segments", + "AssetLinkPrimaryStatusDetails": "google.ads.googleads.v15.common.types.asset_policy", + "AssetUsage": "google.ads.googleads.v15.common.types.asset_usage", + "AudienceDimension": "google.ads.googleads.v15.common.types.audiences", + "AudienceExclusionDimension": "google.ads.googleads.v15.common.types.audiences", + "AudienceInfo": "google.ads.googleads.v15.common.types.criteria", + "AudienceSegment": "google.ads.googleads.v15.common.types.audiences", + "AudienceSegmentDimension": "google.ads.googleads.v15.common.types.audiences", + "BasicUserListInfo": "google.ads.googleads.v15.common.types.user_lists", + "BookOnGoogleAsset": "google.ads.googleads.v15.common.types.asset_types", + "BrandInfo": "google.ads.googleads.v15.common.types.criteria", + "BrandListInfo": "google.ads.googleads.v15.common.types.criteria", + "BudgetCampaignAssociationStatus": "google.ads.googleads.v15.common.types.segments", + "BudgetSimulationPoint": "google.ads.googleads.v15.common.types.simulation", + "BudgetSimulationPointList": "google.ads.googleads.v15.common.types.simulation", + "BusinessNameFilter": "google.ads.googleads.v15.common.types.feed_item_set_filter_type_infos", + "BusinessProfileBusinessNameFilter": "google.ads.googleads.v15.common.types.asset_set_types", + "BusinessProfileLocation": "google.ads.googleads.v15.common.types.asset_types", + "BusinessProfileLocationGroup": "google.ads.googleads.v15.common.types.asset_set_types", + "BusinessProfileLocationSet": "google.ads.googleads.v15.common.types.asset_set_types", + "CallAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "CallAsset": "google.ads.googleads.v15.common.types.asset_types", + "CallFeedItem": "google.ads.googleads.v15.common.types.extensions", + "CalloutAsset": "google.ads.googleads.v15.common.types.asset_types", + "CalloutFeedItem": "google.ads.googleads.v15.common.types.extensions", + "CallToActionAsset": "google.ads.googleads.v15.common.types.asset_types", + "CarrierInfo": "google.ads.googleads.v15.common.types.criteria", + "ChainFilter": "google.ads.googleads.v15.common.types.asset_set_types", + "ChainLocationGroup": "google.ads.googleads.v15.common.types.asset_set_types", + "ChainSet": "google.ads.googleads.v15.common.types.asset_set_types", + "ClickLocation": "google.ads.googleads.v15.common.types.click_location", + "CombinedAudienceInfo": "google.ads.googleads.v15.common.types.criteria", + "Commission": "google.ads.googleads.v15.common.types.bidding", + "ConceptGroup": "google.ads.googleads.v15.common.types.keyword_plan_common", + "Consent": "google.ads.googleads.v15.common.types.consent", + "ContentLabelInfo": "google.ads.googleads.v15.common.types.criteria", + "CpcBidSimulationPoint": "google.ads.googleads.v15.common.types.simulation", + "CpcBidSimulationPointList": "google.ads.googleads.v15.common.types.simulation", + "CpvBidSimulationPoint": "google.ads.googleads.v15.common.types.simulation", + "CpvBidSimulationPointList": "google.ads.googleads.v15.common.types.simulation", + "CriterionCategoryAvailability": "google.ads.googleads.v15.common.types.criterion_category_availability", + "CriterionCategoryChannelAvailability": "google.ads.googleads.v15.common.types.criterion_category_availability", + "CriterionCategoryLocaleAvailability": "google.ads.googleads.v15.common.types.criterion_category_availability", + "CrmBasedUserListInfo": "google.ads.googleads.v15.common.types.user_lists", + "CustomAffinityInfo": "google.ads.googleads.v15.common.types.criteria", + "CustomAudienceInfo": "google.ads.googleads.v15.common.types.criteria", + "CustomAudienceSegment": "google.ads.googleads.v15.common.types.audiences", + "CustomerMatchUserListMetadata": "google.ads.googleads.v15.common.types.offline_user_data", + "CustomIntentInfo": "google.ads.googleads.v15.common.types.criteria", + "CustomizerValue": "google.ads.googleads.v15.common.types.customizer_value", + "CustomParameter": "google.ads.googleads.v15.common.types.custom_parameter", + "DateRange": "google.ads.googleads.v15.common.types.dates", + "DetailedDemographicSegment": "google.ads.googleads.v15.common.types.audiences", + "DeviceInfo": "google.ads.googleads.v15.common.types.criteria", + "DiscoveryCarouselAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "DiscoveryCarouselCardAsset": "google.ads.googleads.v15.common.types.asset_types", + "DiscoveryMultiAssetAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "DiscoveryVideoResponsiveAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "DisplayUploadAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "DynamicAffiliateLocationSetFilter": "google.ads.googleads.v15.common.types.feed_item_set_filter_type_infos", + "DynamicBusinessProfileLocationGroupFilter": "google.ads.googleads.v15.common.types.asset_set_types", + "DynamicCustomAsset": "google.ads.googleads.v15.common.types.asset_types", + "DynamicEducationAsset": "google.ads.googleads.v15.common.types.asset_types", + "DynamicFlightsAsset": "google.ads.googleads.v15.common.types.asset_types", + "DynamicHotelsAndRentalsAsset": "google.ads.googleads.v15.common.types.asset_types", + "DynamicJobsAsset": "google.ads.googleads.v15.common.types.asset_types", + "DynamicLocalAsset": "google.ads.googleads.v15.common.types.asset_types", + "DynamicLocationSetFilter": "google.ads.googleads.v15.common.types.feed_item_set_filter_type_infos", + "DynamicRealEstateAsset": "google.ads.googleads.v15.common.types.asset_types", + "DynamicTravelAsset": "google.ads.googleads.v15.common.types.asset_types", + "EnhancedCpc": "google.ads.googleads.v15.common.types.bidding", + "EventAttribute": "google.ads.googleads.v15.common.types.offline_user_data", + "EventItemAttribute": "google.ads.googleads.v15.common.types.offline_user_data", + "ExclusionSegment": "google.ads.googleads.v15.common.types.audiences", + "ExpandedDynamicSearchAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "ExpandedTextAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "FinalAppUrl": "google.ads.googleads.v15.common.types.final_app_url", + "FlexibleRuleOperandInfo": "google.ads.googleads.v15.common.types.user_lists", + "FlexibleRuleUserListInfo": "google.ads.googleads.v15.common.types.user_lists", + "FrequencyCapEntry": "google.ads.googleads.v15.common.types.frequency_cap", + "FrequencyCapKey": "google.ads.googleads.v15.common.types.frequency_cap", + "GenderDimension": "google.ads.googleads.v15.common.types.audiences", + "GenderInfo": "google.ads.googleads.v15.common.types.criteria", + "GeoPointInfo": "google.ads.googleads.v15.common.types.criteria", + "HistoricalMetricsOptions": "google.ads.googleads.v15.common.types.keyword_plan_common", + "HotelAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "HotelAdvanceBookingWindowInfo": "google.ads.googleads.v15.common.types.criteria", + "HotelCalloutAsset": "google.ads.googleads.v15.common.types.asset_types", + "HotelCalloutFeedItem": "google.ads.googleads.v15.common.types.extensions", + "HotelCheckInDateRangeInfo": "google.ads.googleads.v15.common.types.criteria", + "HotelCheckInDayInfo": "google.ads.googleads.v15.common.types.criteria", + "HotelCityInfo": "google.ads.googleads.v15.common.types.criteria", + "HotelClassInfo": "google.ads.googleads.v15.common.types.criteria", + "HotelCountryRegionInfo": "google.ads.googleads.v15.common.types.criteria", + "HotelDateSelectionTypeInfo": "google.ads.googleads.v15.common.types.criteria", + "HotelIdInfo": "google.ads.googleads.v15.common.types.criteria", + "HotelLengthOfStayInfo": "google.ads.googleads.v15.common.types.criteria", + "HotelPropertyAsset": "google.ads.googleads.v15.common.types.asset_types", + "HotelStateInfo": "google.ads.googleads.v15.common.types.criteria", + "HouseholdIncomeDimension": "google.ads.googleads.v15.common.types.audiences", + "ImageAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "ImageAsset": "google.ads.googleads.v15.common.types.asset_types", + "ImageDimension": "google.ads.googleads.v15.common.types.asset_types", + "ImageFeedItem": "google.ads.googleads.v15.common.types.extensions", + "IncomeRangeInfo": "google.ads.googleads.v15.common.types.criteria", + "InFeedVideoAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "InteractionTypeInfo": "google.ads.googleads.v15.common.types.criteria", + "IpBlockInfo": "google.ads.googleads.v15.common.types.criteria", + "ItemAttribute": "google.ads.googleads.v15.common.types.offline_user_data", + "Keyword": "google.ads.googleads.v15.common.types.segments", + "KeywordAnnotations": "google.ads.googleads.v15.common.types.keyword_plan_common", + "KeywordConcept": "google.ads.googleads.v15.common.types.keyword_plan_common", + "KeywordInfo": "google.ads.googleads.v15.common.types.criteria", + "KeywordPlanAggregateMetricResults": "google.ads.googleads.v15.common.types.keyword_plan_common", + "KeywordPlanAggregateMetrics": "google.ads.googleads.v15.common.types.keyword_plan_common", + "KeywordPlanDeviceSearches": "google.ads.googleads.v15.common.types.keyword_plan_common", + "KeywordPlanHistoricalMetrics": "google.ads.googleads.v15.common.types.keyword_plan_common", + "KeywordThemeInfo": "google.ads.googleads.v15.common.types.criteria", + "LanguageInfo": "google.ads.googleads.v15.common.types.criteria", + "LeadFormAsset": "google.ads.googleads.v15.common.types.asset_types", + "LeadFormCustomQuestionField": "google.ads.googleads.v15.common.types.asset_types", + "LeadFormDeliveryMethod": "google.ads.googleads.v15.common.types.asset_types", + "LeadFormField": "google.ads.googleads.v15.common.types.asset_types", + "LeadFormSingleChoiceAnswers": "google.ads.googleads.v15.common.types.asset_types", + "LegacyAppInstallAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "LegacyResponsiveDisplayAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "LifecycleGoalValueSettings": "google.ads.googleads.v15.common.types.lifecycle_goals", + "LifeEventSegment": "google.ads.googleads.v15.common.types.audiences", + "ListingDimensionInfo": "google.ads.googleads.v15.common.types.criteria", + "ListingDimensionPath": "google.ads.googleads.v15.common.types.criteria", + "ListingGroupInfo": "google.ads.googleads.v15.common.types.criteria", + "ListingScopeInfo": "google.ads.googleads.v15.common.types.criteria", + "LocalAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "LocalServiceIdInfo": "google.ads.googleads.v15.common.types.criteria", + "LocalServicesDocumentReadOnly": "google.ads.googleads.v15.common.types.local_services", + "LocationAsset": "google.ads.googleads.v15.common.types.asset_types", + "LocationFeedItem": "google.ads.googleads.v15.common.types.extensions", + "LocationGroupInfo": "google.ads.googleads.v15.common.types.criteria", + "LocationInfo": "google.ads.googleads.v15.common.types.criteria", + "LocationSet": "google.ads.googleads.v15.common.types.asset_set_types", + "LogicalUserListInfo": "google.ads.googleads.v15.common.types.user_lists", + "LogicalUserListOperandInfo": "google.ads.googleads.v15.common.types.user_lists", + "LookalikeUserListInfo": "google.ads.googleads.v15.common.types.user_lists", + "ManualCpa": "google.ads.googleads.v15.common.types.bidding", + "ManualCpc": "google.ads.googleads.v15.common.types.bidding", + "ManualCpm": "google.ads.googleads.v15.common.types.bidding", + "ManualCpv": "google.ads.googleads.v15.common.types.bidding", + "MapsLocationInfo": "google.ads.googleads.v15.common.types.asset_set_types", + "MapsLocationSet": "google.ads.googleads.v15.common.types.asset_set_types", + "MatchingFunction": "google.ads.googleads.v15.common.types.matching_function", + "MaximizeConversions": "google.ads.googleads.v15.common.types.bidding", + "MaximizeConversionValue": "google.ads.googleads.v15.common.types.bidding", + "MediaBundleAsset": "google.ads.googleads.v15.common.types.asset_types", + "MetricGoal": "google.ads.googleads.v15.common.types.metric_goal", + "Metrics": "google.ads.googleads.v15.common.types.metrics", + "MobileAppAsset": "google.ads.googleads.v15.common.types.asset_types", + "MobileAppCategoryInfo": "google.ads.googleads.v15.common.types.criteria", + "MobileApplicationInfo": "google.ads.googleads.v15.common.types.criteria", + "MobileDeviceInfo": "google.ads.googleads.v15.common.types.criteria", + "Money": "google.ads.googleads.v15.common.types.feed_common", + "MonthlySearchVolume": "google.ads.googleads.v15.common.types.keyword_plan_common", + "NegativeKeywordListInfo": "google.ads.googleads.v15.common.types.criteria", + "OfflineUserAddressInfo": "google.ads.googleads.v15.common.types.offline_user_data", + "Operand": "google.ads.googleads.v15.common.types.matching_function", + "OperatingSystemVersionInfo": "google.ads.googleads.v15.common.types.criteria", + "PageFeedAsset": "google.ads.googleads.v15.common.types.asset_types", + "ParentalStatusDimension": "google.ads.googleads.v15.common.types.audiences", + "ParentalStatusInfo": "google.ads.googleads.v15.common.types.criteria", + "PercentCpc": "google.ads.googleads.v15.common.types.bidding", + "PercentCpcBidSimulationPoint": "google.ads.googleads.v15.common.types.simulation", + "PercentCpcBidSimulationPointList": "google.ads.googleads.v15.common.types.simulation", + "PlacementInfo": "google.ads.googleads.v15.common.types.criteria", + "PolicySummary": "google.ads.googleads.v15.common.types.policy_summary", + "PolicyTopicConstraint": "google.ads.googleads.v15.common.types.policy", + "PolicyTopicEntry": "google.ads.googleads.v15.common.types.policy", + "PolicyTopicEvidence": "google.ads.googleads.v15.common.types.policy", + "PolicyValidationParameter": "google.ads.googleads.v15.common.types.policy", + "PolicyViolationKey": "google.ads.googleads.v15.common.types.policy", + "PriceAsset": "google.ads.googleads.v15.common.types.asset_types", + "PriceFeedItem": "google.ads.googleads.v15.common.types.extensions", + "PriceOffer": "google.ads.googleads.v15.common.types.extensions", + "PriceOffering": "google.ads.googleads.v15.common.types.asset_types", + "ProductBrandInfo": "google.ads.googleads.v15.common.types.criteria", + "ProductCategoryInfo": "google.ads.googleads.v15.common.types.criteria", + "ProductChannelExclusivityInfo": "google.ads.googleads.v15.common.types.criteria", + "ProductChannelInfo": "google.ads.googleads.v15.common.types.criteria", + "ProductConditionInfo": "google.ads.googleads.v15.common.types.criteria", + "ProductCustomAttributeInfo": "google.ads.googleads.v15.common.types.criteria", + "ProductGroupingInfo": "google.ads.googleads.v15.common.types.criteria", + "ProductItemIdInfo": "google.ads.googleads.v15.common.types.criteria", + "ProductLabelsInfo": "google.ads.googleads.v15.common.types.criteria", + "ProductLegacyConditionInfo": "google.ads.googleads.v15.common.types.criteria", + "ProductTypeFullInfo": "google.ads.googleads.v15.common.types.criteria", + "ProductTypeInfo": "google.ads.googleads.v15.common.types.criteria", + "PromotionAsset": "google.ads.googleads.v15.common.types.asset_types", + "PromotionFeedItem": "google.ads.googleads.v15.common.types.extensions", + "ProximityInfo": "google.ads.googleads.v15.common.types.criteria", + "RealTimeBiddingSetting": "google.ads.googleads.v15.common.types.real_time_bidding_setting", + "ResponsiveDisplayAdControlSpec": "google.ads.googleads.v15.common.types.ad_type_infos", + "ResponsiveDisplayAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "ResponsiveSearchAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "RuleBasedUserListInfo": "google.ads.googleads.v15.common.types.user_lists", + "SearchThemeInfo": "google.ads.googleads.v15.common.types.criteria", + "SearchVolumeRange": "google.ads.googleads.v15.common.types.metrics", + "Segments": "google.ads.googleads.v15.common.types.segments", + "ShoppingComparisonListingAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "ShoppingLoyalty": "google.ads.googleads.v15.common.types.offline_user_data", + "ShoppingProductAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "ShoppingSmartAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "SimilarUserListInfo": "google.ads.googleads.v15.common.types.user_lists", + "SitelinkAsset": "google.ads.googleads.v15.common.types.asset_types", + "SitelinkFeedItem": "google.ads.googleads.v15.common.types.extensions", + "SkAdNetworkSourceApp": "google.ads.googleads.v15.common.types.segments", + "SmartCampaignAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "StoreAttribute": "google.ads.googleads.v15.common.types.offline_user_data", + "StoreSalesMetadata": "google.ads.googleads.v15.common.types.offline_user_data", + "StoreSalesThirdPartyMetadata": "google.ads.googleads.v15.common.types.offline_user_data", + "StructuredSnippetAsset": "google.ads.googleads.v15.common.types.asset_types", + "StructuredSnippetFeedItem": "google.ads.googleads.v15.common.types.extensions", + "TagSnippet": "google.ads.googleads.v15.common.types.tag_snippet", + "TargetCpa": "google.ads.googleads.v15.common.types.bidding", + "TargetCpaSimulationPoint": "google.ads.googleads.v15.common.types.simulation", + "TargetCpaSimulationPointList": "google.ads.googleads.v15.common.types.simulation", + "TargetCpm": "google.ads.googleads.v15.common.types.bidding", + "TargetCpmTargetFrequencyGoal": "google.ads.googleads.v15.common.types.bidding", + "TargetImpressionShare": "google.ads.googleads.v15.common.types.bidding", + "TargetImpressionShareSimulationPoint": "google.ads.googleads.v15.common.types.simulation", + "TargetImpressionShareSimulationPointList": "google.ads.googleads.v15.common.types.simulation", + "TargetingSetting": "google.ads.googleads.v15.common.types.targeting_setting", + "TargetRestriction": "google.ads.googleads.v15.common.types.targeting_setting", + "TargetRestrictionOperation": "google.ads.googleads.v15.common.types.targeting_setting", + "TargetRoas": "google.ads.googleads.v15.common.types.bidding", + "TargetRoasSimulationPoint": "google.ads.googleads.v15.common.types.simulation", + "TargetRoasSimulationPointList": "google.ads.googleads.v15.common.types.simulation", + "TargetSpend": "google.ads.googleads.v15.common.types.bidding", + "TextAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "TextAsset": "google.ads.googleads.v15.common.types.asset_types", + "TextLabel": "google.ads.googleads.v15.common.types.text_label", + "TextMessageFeedItem": "google.ads.googleads.v15.common.types.extensions", + "TopicInfo": "google.ads.googleads.v15.common.types.criteria", + "TransactionAttribute": "google.ads.googleads.v15.common.types.offline_user_data", + "TravelAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "UnknownListingDimensionInfo": "google.ads.googleads.v15.common.types.criteria", + "UrlCollection": "google.ads.googleads.v15.common.types.url_collection", + "UserAttribute": "google.ads.googleads.v15.common.types.offline_user_data", + "UserData": "google.ads.googleads.v15.common.types.offline_user_data", + "UserIdentifier": "google.ads.googleads.v15.common.types.offline_user_data", + "UserInterestInfo": "google.ads.googleads.v15.common.types.criteria", + "UserInterestSegment": "google.ads.googleads.v15.common.types.audiences", + "UserListActionInfo": "google.ads.googleads.v15.common.types.user_lists", + "UserListDateRuleItemInfo": "google.ads.googleads.v15.common.types.user_lists", + "UserListInfo": "google.ads.googleads.v15.common.types.criteria", + "UserListLogicalRuleInfo": "google.ads.googleads.v15.common.types.user_lists", + "UserListNumberRuleItemInfo": "google.ads.googleads.v15.common.types.user_lists", + "UserListRuleInfo": "google.ads.googleads.v15.common.types.user_lists", + "UserListRuleItemGroupInfo": "google.ads.googleads.v15.common.types.user_lists", + "UserListRuleItemInfo": "google.ads.googleads.v15.common.types.user_lists", + "UserListSegment": "google.ads.googleads.v15.common.types.audiences", + "UserListStringRuleItemInfo": "google.ads.googleads.v15.common.types.user_lists", + "Value": "google.ads.googleads.v15.common.types.value", + "VideoAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "VideoBumperInStreamAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "VideoNonSkippableInStreamAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "VideoOutstreamAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "VideoResponsiveAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "VideoTrueViewInStreamAdInfo": "google.ads.googleads.v15.common.types.ad_type_infos", + "WebhookDelivery": "google.ads.googleads.v15.common.types.asset_types", + "WebpageConditionInfo": "google.ads.googleads.v15.common.types.criteria", + "WebpageInfo": "google.ads.googleads.v15.common.types.criteria", + "WebpageSampleInfo": "google.ads.googleads.v15.common.types.criteria", + "YearMonth": "google.ads.googleads.v15.common.types.dates", + "YearMonthRange": "google.ads.googleads.v15.common.types.dates", + "YouTubeChannelInfo": "google.ads.googleads.v15.common.types.criteria", + "YoutubeVideoAsset": "google.ads.googleads.v15.common.types.asset_types", + "YouTubeVideoInfo": "google.ads.googleads.v15.common.types.criteria", + "AccessInvitationStatusEnum": "google.ads.googleads.v15.enums.types.access_invitation_status", + "AccessReasonEnum": "google.ads.googleads.v15.enums.types.access_reason", + "AccessRoleEnum": "google.ads.googleads.v15.enums.types.access_role", + "AccountBudgetProposalStatusEnum": "google.ads.googleads.v15.enums.types.account_budget_proposal_status", + "AccountBudgetProposalTypeEnum": "google.ads.googleads.v15.enums.types.account_budget_proposal_type", + "AccountBudgetStatusEnum": "google.ads.googleads.v15.enums.types.account_budget_status", + "AccountLinkStatusEnum": "google.ads.googleads.v15.enums.types.account_link_status", + "AdCustomizerPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.ad_customizer_placeholder_field", + "AdDestinationTypeEnum": "google.ads.googleads.v15.enums.types.ad_destination_type", + "AdGroupAdRotationModeEnum": "google.ads.googleads.v15.enums.types.ad_group_ad_rotation_mode", + "AdGroupAdStatusEnum": "google.ads.googleads.v15.enums.types.ad_group_ad_status", + "AdGroupCriterionApprovalStatusEnum": "google.ads.googleads.v15.enums.types.ad_group_criterion_approval_status", + "AdGroupCriterionStatusEnum": "google.ads.googleads.v15.enums.types.ad_group_criterion_status", + "AdGroupStatusEnum": "google.ads.googleads.v15.enums.types.ad_group_status", + "AdGroupTypeEnum": "google.ads.googleads.v15.enums.types.ad_group_type", + "AdNetworkTypeEnum": "google.ads.googleads.v15.enums.types.ad_network_type", + "AdServingOptimizationStatusEnum": "google.ads.googleads.v15.enums.types.ad_serving_optimization_status", + "AdStrengthEnum": "google.ads.googleads.v15.enums.types.ad_strength", + "AdTypeEnum": "google.ads.googleads.v15.enums.types.ad_type", + "AdvertisingChannelSubTypeEnum": "google.ads.googleads.v15.enums.types.advertising_channel_sub_type", + "AdvertisingChannelTypeEnum": "google.ads.googleads.v15.enums.types.advertising_channel_type", + "AffiliateLocationFeedRelationshipTypeEnum": "google.ads.googleads.v15.enums.types.affiliate_location_feed_relationship_type", + "AffiliateLocationPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.affiliate_location_placeholder_field", + "AgeRangeTypeEnum": "google.ads.googleads.v15.enums.types.age_range_type", + "AndroidPrivacyInteractionTypeEnum": "google.ads.googleads.v15.enums.types.android_privacy_interaction_type", + "AndroidPrivacyNetworkTypeEnum": "google.ads.googleads.v15.enums.types.android_privacy_network_type", + "AppBiddingGoalEnum": "google.ads.googleads.v15.enums.types.app_bidding_goal", + "AppCampaignAppStoreEnum": "google.ads.googleads.v15.enums.types.app_campaign_app_store", + "AppCampaignBiddingStrategyGoalTypeEnum": "google.ads.googleads.v15.enums.types.app_campaign_bidding_strategy_goal_type", + "AppPaymentModelTypeEnum": "google.ads.googleads.v15.enums.types.app_payment_model_type", + "AppPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.app_placeholder_field", + "AppStoreEnum": "google.ads.googleads.v15.enums.types.app_store", + "AppUrlOperatingSystemTypeEnum": "google.ads.googleads.v15.enums.types.app_url_operating_system_type", + "AssetAutomationStatusEnum": "google.ads.googleads.v15.enums.types.asset_automation_status", + "AssetAutomationTypeEnum": "google.ads.googleads.v15.enums.types.asset_automation_type", + "AssetFieldTypeEnum": "google.ads.googleads.v15.enums.types.asset_field_type", + "AssetGroupPrimaryStatusEnum": "google.ads.googleads.v15.enums.types.asset_group_primary_status", + "AssetGroupPrimaryStatusReasonEnum": "google.ads.googleads.v15.enums.types.asset_group_primary_status_reason", + "AssetGroupSignalApprovalStatusEnum": "google.ads.googleads.v15.enums.types.asset_group_signal_approval_status", + "AssetGroupStatusEnum": "google.ads.googleads.v15.enums.types.asset_group_status", + "AssetLinkPrimaryStatusEnum": "google.ads.googleads.v15.enums.types.asset_link_primary_status", + "AssetLinkPrimaryStatusReasonEnum": "google.ads.googleads.v15.enums.types.asset_link_primary_status_reason", + "AssetLinkStatusEnum": "google.ads.googleads.v15.enums.types.asset_link_status", + "AssetOfflineEvaluationErrorReasonsEnum": "google.ads.googleads.v15.enums.types.asset_offline_evaluation_error_reasons", + "AssetPerformanceLabelEnum": "google.ads.googleads.v15.enums.types.asset_performance_label", + "AssetSetAssetStatusEnum": "google.ads.googleads.v15.enums.types.asset_set_asset_status", + "AssetSetLinkStatusEnum": "google.ads.googleads.v15.enums.types.asset_set_link_status", + "AssetSetStatusEnum": "google.ads.googleads.v15.enums.types.asset_set_status", + "AssetSetTypeEnum": "google.ads.googleads.v15.enums.types.asset_set_type", + "AssetSourceEnum": "google.ads.googleads.v15.enums.types.asset_source", + "AssetTypeEnum": "google.ads.googleads.v15.enums.types.asset_type", + "AsyncActionStatusEnum": "google.ads.googleads.v15.enums.types.async_action_status", + "AttributionModelEnum": "google.ads.googleads.v15.enums.types.attribution_model", + "AudienceInsightsDimensionEnum": "google.ads.googleads.v15.enums.types.audience_insights_dimension", + "AudienceScopeEnum": "google.ads.googleads.v15.enums.types.audience_scope", + "AudienceStatusEnum": "google.ads.googleads.v15.enums.types.audience_status", + "BatchJobStatusEnum": "google.ads.googleads.v15.enums.types.batch_job_status", + "BiddingSourceEnum": "google.ads.googleads.v15.enums.types.bidding_source", + "BiddingStrategyStatusEnum": "google.ads.googleads.v15.enums.types.bidding_strategy_status", + "BiddingStrategySystemStatusEnum": "google.ads.googleads.v15.enums.types.bidding_strategy_system_status", + "BiddingStrategyTypeEnum": "google.ads.googleads.v15.enums.types.bidding_strategy_type", + "BidModifierSourceEnum": "google.ads.googleads.v15.enums.types.bid_modifier_source", + "BillingSetupStatusEnum": "google.ads.googleads.v15.enums.types.billing_setup_status", + "BrandSafetySuitabilityEnum": "google.ads.googleads.v15.enums.types.brand_safety_suitability", + "BrandStateEnum": "google.ads.googleads.v15.enums.types.brand_state", + "BudgetCampaignAssociationStatusEnum": "google.ads.googleads.v15.enums.types.budget_campaign_association_status", + "BudgetDeliveryMethodEnum": "google.ads.googleads.v15.enums.types.budget_delivery_method", + "BudgetPeriodEnum": "google.ads.googleads.v15.enums.types.budget_period", + "BudgetStatusEnum": "google.ads.googleads.v15.enums.types.budget_status", + "BudgetTypeEnum": "google.ads.googleads.v15.enums.types.budget_type", + "CallConversionReportingStateEnum": "google.ads.googleads.v15.enums.types.call_conversion_reporting_state", + "CalloutPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.callout_placeholder_field", + "CallPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.call_placeholder_field", + "CallToActionTypeEnum": "google.ads.googleads.v15.enums.types.call_to_action_type", + "CallTrackingDisplayLocationEnum": "google.ads.googleads.v15.enums.types.call_tracking_display_location", + "CallTypeEnum": "google.ads.googleads.v15.enums.types.call_type", + "CampaignCriterionStatusEnum": "google.ads.googleads.v15.enums.types.campaign_criterion_status", + "CampaignDraftStatusEnum": "google.ads.googleads.v15.enums.types.campaign_draft_status", + "CampaignExperimentTypeEnum": "google.ads.googleads.v15.enums.types.campaign_experiment_type", + "CampaignGroupStatusEnum": "google.ads.googleads.v15.enums.types.campaign_group_status", + "CampaignPrimaryStatusEnum": "google.ads.googleads.v15.enums.types.campaign_primary_status", + "CampaignPrimaryStatusReasonEnum": "google.ads.googleads.v15.enums.types.campaign_primary_status_reason", + "CampaignServingStatusEnum": "google.ads.googleads.v15.enums.types.campaign_serving_status", + "CampaignSharedSetStatusEnum": "google.ads.googleads.v15.enums.types.campaign_shared_set_status", + "CampaignStatusEnum": "google.ads.googleads.v15.enums.types.campaign_status", + "ChainRelationshipTypeEnum": "google.ads.googleads.v15.enums.types.chain_relationship_type", + "ChangeClientTypeEnum": "google.ads.googleads.v15.enums.types.change_client_type", + "ChangeEventResourceTypeEnum": "google.ads.googleads.v15.enums.types.change_event_resource_type", + "ChangeStatusOperationEnum": "google.ads.googleads.v15.enums.types.change_status_operation", + "ChangeStatusResourceTypeEnum": "google.ads.googleads.v15.enums.types.change_status_resource_type", + "ClickTypeEnum": "google.ads.googleads.v15.enums.types.click_type", + "CombinedAudienceStatusEnum": "google.ads.googleads.v15.enums.types.combined_audience_status", + "ConsentStatusEnum": "google.ads.googleads.v15.enums.types.consent_status", + "ContentLabelTypeEnum": "google.ads.googleads.v15.enums.types.content_label_type", + "ConversionActionCategoryEnum": "google.ads.googleads.v15.enums.types.conversion_action_category", + "ConversionActionCountingTypeEnum": "google.ads.googleads.v15.enums.types.conversion_action_counting_type", + "ConversionActionStatusEnum": "google.ads.googleads.v15.enums.types.conversion_action_status", + "ConversionActionTypeEnum": "google.ads.googleads.v15.enums.types.conversion_action_type", + "ConversionAdjustmentTypeEnum": "google.ads.googleads.v15.enums.types.conversion_adjustment_type", + "ConversionAttributionEventTypeEnum": "google.ads.googleads.v15.enums.types.conversion_attribution_event_type", + "ConversionCustomVariableStatusEnum": "google.ads.googleads.v15.enums.types.conversion_custom_variable_status", + "ConversionEnvironmentEnum": "google.ads.googleads.v15.enums.types.conversion_environment_enum", + "ConversionLagBucketEnum": "google.ads.googleads.v15.enums.types.conversion_lag_bucket", + "ConversionOrAdjustmentLagBucketEnum": "google.ads.googleads.v15.enums.types.conversion_or_adjustment_lag_bucket", + "ConversionOriginEnum": "google.ads.googleads.v15.enums.types.conversion_origin", + "ConversionTrackingStatusEnum": "google.ads.googleads.v15.enums.types.conversion_tracking_status_enum", + "ConversionValueRulePrimaryDimensionEnum": "google.ads.googleads.v15.enums.types.conversion_value_rule_primary_dimension", + "ConversionValueRuleSetStatusEnum": "google.ads.googleads.v15.enums.types.conversion_value_rule_set_status", + "ConversionValueRuleStatusEnum": "google.ads.googleads.v15.enums.types.conversion_value_rule_status", + "ConvertingUserPriorEngagementTypeAndLtvBucketEnum": "google.ads.googleads.v15.enums.types.converting_user_prior_engagement_type_and_ltv_bucket", + "CriterionCategoryChannelAvailabilityModeEnum": "google.ads.googleads.v15.enums.types.criterion_category_channel_availability_mode", + "CriterionCategoryLocaleAvailabilityModeEnum": "google.ads.googleads.v15.enums.types.criterion_category_locale_availability_mode", + "CriterionSystemServingStatusEnum": "google.ads.googleads.v15.enums.types.criterion_system_serving_status", + "CriterionTypeEnum": "google.ads.googleads.v15.enums.types.criterion_type", + "CustomAudienceMemberTypeEnum": "google.ads.googleads.v15.enums.types.custom_audience_member_type", + "CustomAudienceStatusEnum": "google.ads.googleads.v15.enums.types.custom_audience_status", + "CustomAudienceTypeEnum": "google.ads.googleads.v15.enums.types.custom_audience_type", + "CustomConversionGoalStatusEnum": "google.ads.googleads.v15.enums.types.custom_conversion_goal_status", + "CustomerAcquisitionOptimizationModeEnum": "google.ads.googleads.v15.enums.types.customer_acquisition_optimization_mode", + "CustomerMatchUploadKeyTypeEnum": "google.ads.googleads.v15.enums.types.customer_match_upload_key_type", + "CustomerPayPerConversionEligibilityFailureReasonEnum": "google.ads.googleads.v15.enums.types.customer_pay_per_conversion_eligibility_failure_reason", + "CustomerStatusEnum": "google.ads.googleads.v15.enums.types.customer_status", + "CustomInterestMemberTypeEnum": "google.ads.googleads.v15.enums.types.custom_interest_member_type", + "CustomInterestStatusEnum": "google.ads.googleads.v15.enums.types.custom_interest_status", + "CustomInterestTypeEnum": "google.ads.googleads.v15.enums.types.custom_interest_type", + "CustomizerAttributeStatusEnum": "google.ads.googleads.v15.enums.types.customizer_attribute_status", + "CustomizerAttributeTypeEnum": "google.ads.googleads.v15.enums.types.customizer_attribute_type", + "CustomizerValueStatusEnum": "google.ads.googleads.v15.enums.types.customizer_value_status", + "CustomPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.custom_placeholder_field", + "DataDrivenModelStatusEnum": "google.ads.googleads.v15.enums.types.data_driven_model_status", + "DayOfWeekEnum": "google.ads.googleads.v15.enums.types.day_of_week", + "DeviceEnum": "google.ads.googleads.v15.enums.types.device", + "DisplayAdFormatSettingEnum": "google.ads.googleads.v15.enums.types.display_ad_format_setting", + "DisplayUploadProductTypeEnum": "google.ads.googleads.v15.enums.types.display_upload_product_type", + "DistanceBucketEnum": "google.ads.googleads.v15.enums.types.distance_bucket", + "DsaPageFeedCriterionFieldEnum": "google.ads.googleads.v15.enums.types.dsa_page_feed_criterion_field", + "EducationPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.education_placeholder_field", + "ExperimentMetricDirectionEnum": "google.ads.googleads.v15.enums.types.experiment_metric_direction", + "ExperimentMetricEnum": "google.ads.googleads.v15.enums.types.experiment_metric", + "ExperimentStatusEnum": "google.ads.googleads.v15.enums.types.experiment_status", + "ExperimentTypeEnum": "google.ads.googleads.v15.enums.types.experiment_type", + "ExtensionSettingDeviceEnum": "google.ads.googleads.v15.enums.types.extension_setting_device", + "ExtensionTypeEnum": "google.ads.googleads.v15.enums.types.extension_type", + "ExternalConversionSourceEnum": "google.ads.googleads.v15.enums.types.external_conversion_source", + "FeedAttributeTypeEnum": "google.ads.googleads.v15.enums.types.feed_attribute_type", + "FeedItemQualityApprovalStatusEnum": "google.ads.googleads.v15.enums.types.feed_item_quality_approval_status", + "FeedItemQualityDisapprovalReasonEnum": "google.ads.googleads.v15.enums.types.feed_item_quality_disapproval_reason", + "FeedItemSetStatusEnum": "google.ads.googleads.v15.enums.types.feed_item_set_status", + "FeedItemSetStringFilterTypeEnum": "google.ads.googleads.v15.enums.types.feed_item_set_string_filter_type", + "FeedItemStatusEnum": "google.ads.googleads.v15.enums.types.feed_item_status", + "FeedItemTargetDeviceEnum": "google.ads.googleads.v15.enums.types.feed_item_target_device", + "FeedItemTargetStatusEnum": "google.ads.googleads.v15.enums.types.feed_item_target_status", + "FeedItemTargetTypeEnum": "google.ads.googleads.v15.enums.types.feed_item_target_type", + "FeedItemValidationStatusEnum": "google.ads.googleads.v15.enums.types.feed_item_validation_status", + "FeedLinkStatusEnum": "google.ads.googleads.v15.enums.types.feed_link_status", + "FeedMappingCriterionTypeEnum": "google.ads.googleads.v15.enums.types.feed_mapping_criterion_type", + "FeedMappingStatusEnum": "google.ads.googleads.v15.enums.types.feed_mapping_status", + "FeedOriginEnum": "google.ads.googleads.v15.enums.types.feed_origin", + "FeedStatusEnum": "google.ads.googleads.v15.enums.types.feed_status", + "FlightPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.flight_placeholder_field", + "FrequencyCapEventTypeEnum": "google.ads.googleads.v15.enums.types.frequency_cap_event_type", + "FrequencyCapLevelEnum": "google.ads.googleads.v15.enums.types.frequency_cap_level", + "FrequencyCapTimeUnitEnum": "google.ads.googleads.v15.enums.types.frequency_cap_time_unit", + "GenderTypeEnum": "google.ads.googleads.v15.enums.types.gender_type", + "GeoTargetConstantStatusEnum": "google.ads.googleads.v15.enums.types.geo_target_constant_status", + "GeoTargetingRestrictionEnum": "google.ads.googleads.v15.enums.types.geo_targeting_restriction", + "GeoTargetingTypeEnum": "google.ads.googleads.v15.enums.types.geo_targeting_type", + "GoalConfigLevelEnum": "google.ads.googleads.v15.enums.types.goal_config_level", + "GoogleAdsFieldCategoryEnum": "google.ads.googleads.v15.enums.types.google_ads_field_category", + "GoogleAdsFieldDataTypeEnum": "google.ads.googleads.v15.enums.types.google_ads_field_data_type", + "GoogleVoiceCallStatusEnum": "google.ads.googleads.v15.enums.types.google_voice_call_status", + "HotelAssetSuggestionStatusEnum": "google.ads.googleads.v15.enums.types.hotel_asset_suggestion_status", + "HotelDateSelectionTypeEnum": "google.ads.googleads.v15.enums.types.hotel_date_selection_type", + "HotelPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.hotel_placeholder_field", + "HotelPriceBucketEnum": "google.ads.googleads.v15.enums.types.hotel_price_bucket", + "HotelRateTypeEnum": "google.ads.googleads.v15.enums.types.hotel_rate_type", + "HotelReconciliationStatusEnum": "google.ads.googleads.v15.enums.types.hotel_reconciliation_status", + "ImagePlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.image_placeholder_field", + "IncomeRangeTypeEnum": "google.ads.googleads.v15.enums.types.income_range_type", + "InteractionEventTypeEnum": "google.ads.googleads.v15.enums.types.interaction_event_type", + "InteractionTypeEnum": "google.ads.googleads.v15.enums.types.interaction_type", + "InvoiceTypeEnum": "google.ads.googleads.v15.enums.types.invoice_type", + "JobPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.job_placeholder_field", + "KeywordMatchTypeEnum": "google.ads.googleads.v15.enums.types.keyword_match_type", + "KeywordPlanAggregateMetricTypeEnum": "google.ads.googleads.v15.enums.types.keyword_plan_aggregate_metric_type", + "KeywordPlanCompetitionLevelEnum": "google.ads.googleads.v15.enums.types.keyword_plan_competition_level", + "KeywordPlanConceptGroupTypeEnum": "google.ads.googleads.v15.enums.types.keyword_plan_concept_group_type", + "KeywordPlanForecastIntervalEnum": "google.ads.googleads.v15.enums.types.keyword_plan_forecast_interval", + "KeywordPlanKeywordAnnotationEnum": "google.ads.googleads.v15.enums.types.keyword_plan_keyword_annotation", + "KeywordPlanNetworkEnum": "google.ads.googleads.v15.enums.types.keyword_plan_network", + "LabelStatusEnum": "google.ads.googleads.v15.enums.types.label_status", + "LeadFormCallToActionTypeEnum": "google.ads.googleads.v15.enums.types.lead_form_call_to_action_type", + "LeadFormDesiredIntentEnum": "google.ads.googleads.v15.enums.types.lead_form_desired_intent", + "LeadFormFieldUserInputTypeEnum": "google.ads.googleads.v15.enums.types.lead_form_field_user_input_type", + "LeadFormPostSubmitCallToActionTypeEnum": "google.ads.googleads.v15.enums.types.lead_form_post_submit_call_to_action_type", + "LegacyAppInstallAdAppStoreEnum": "google.ads.googleads.v15.enums.types.legacy_app_install_ad_app_store", + "LinkedAccountTypeEnum": "google.ads.googleads.v15.enums.types.linked_account_type", + "LinkedProductTypeEnum": "google.ads.googleads.v15.enums.types.linked_product_type", + "ListingGroupFilterCustomAttributeIndexEnum": "google.ads.googleads.v15.enums.types.listing_group_filter_custom_attribute_index", + "ListingGroupFilterListingSourceEnum": "google.ads.googleads.v15.enums.types.listing_group_filter_listing_source", + "ListingGroupFilterProductCategoryLevelEnum": "google.ads.googleads.v15.enums.types.listing_group_filter_product_category_level", + "ListingGroupFilterProductChannelEnum": "google.ads.googleads.v15.enums.types.listing_group_filter_product_channel", + "ListingGroupFilterProductConditionEnum": "google.ads.googleads.v15.enums.types.listing_group_filter_product_condition", + "ListingGroupFilterProductTypeLevelEnum": "google.ads.googleads.v15.enums.types.listing_group_filter_product_type_level", + "ListingGroupFilterTypeEnum": "google.ads.googleads.v15.enums.types.listing_group_filter_type_enum", + "ListingGroupTypeEnum": "google.ads.googleads.v15.enums.types.listing_group_type", + "ListingTypeEnum": "google.ads.googleads.v15.enums.types.listing_type", + "LocalPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.local_placeholder_field", + "LocalServicesInsuranceRejectionReasonEnum": "google.ads.googleads.v15.enums.types.local_services_insurance_rejection_reason", + "LocalServicesLeadConversationTypeEnum": "google.ads.googleads.v15.enums.types.local_services_conversation_type", + "LocalServicesLeadStatusEnum": "google.ads.googleads.v15.enums.types.local_services_lead_status", + "LocalServicesLeadTypeEnum": "google.ads.googleads.v15.enums.types.local_services_lead_type", + "LocalServicesLicenseRejectionReasonEnum": "google.ads.googleads.v15.enums.types.local_services_license_rejection_reason", + "LocalServicesParticipantTypeEnum": "google.ads.googleads.v15.enums.types.local_services_participant_type", + "LocalServicesVerificationArtifactStatusEnum": "google.ads.googleads.v15.enums.types.local_services_verification_artifact_status", + "LocalServicesVerificationArtifactTypeEnum": "google.ads.googleads.v15.enums.types.local_services_verification_artifact_type", + "LocalServicesVerificationStatusEnum": "google.ads.googleads.v15.enums.types.local_services_verification_status", + "LocationExtensionTargetingCriterionFieldEnum": "google.ads.googleads.v15.enums.types.location_extension_targeting_criterion_field", + "LocationGroupRadiusUnitsEnum": "google.ads.googleads.v15.enums.types.location_group_radius_units", + "LocationOwnershipTypeEnum": "google.ads.googleads.v15.enums.types.location_ownership_type", + "LocationPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.location_placeholder_field", + "LocationSourceTypeEnum": "google.ads.googleads.v15.enums.types.location_source_type", + "LocationStringFilterTypeEnum": "google.ads.googleads.v15.enums.types.location_string_filter_type", + "LookalikeExpansionLevelEnum": "google.ads.googleads.v15.enums.types.lookalike_expansion_level", + "ManagerLinkStatusEnum": "google.ads.googleads.v15.enums.types.manager_link_status", + "MatchingFunctionContextTypeEnum": "google.ads.googleads.v15.enums.types.matching_function_context_type", + "MatchingFunctionOperatorEnum": "google.ads.googleads.v15.enums.types.matching_function_operator", + "MediaTypeEnum": "google.ads.googleads.v15.enums.types.media_type", + "MessagePlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.message_placeholder_field", + "MimeTypeEnum": "google.ads.googleads.v15.enums.types.mime_type", + "MinuteOfHourEnum": "google.ads.googleads.v15.enums.types.minute_of_hour", + "MobileAppVendorEnum": "google.ads.googleads.v15.enums.types.mobile_app_vendor", + "MobileDeviceTypeEnum": "google.ads.googleads.v15.enums.types.mobile_device_type", + "MonthOfYearEnum": "google.ads.googleads.v15.enums.types.month_of_year", + "NegativeGeoTargetTypeEnum": "google.ads.googleads.v15.enums.types.negative_geo_target_type", + "OfflineConversionDiagnosticStatusEnum": "google.ads.googleads.v15.enums.types.offline_conversion_diagnostic_status_enum", + "OfflineEventUploadClientEnum": "google.ads.googleads.v15.enums.types.offline_event_upload_client_enum", + "OfflineUserDataJobFailureReasonEnum": "google.ads.googleads.v15.enums.types.offline_user_data_job_failure_reason", + "OfflineUserDataJobMatchRateRangeEnum": "google.ads.googleads.v15.enums.types.offline_user_data_job_match_rate_range", + "OfflineUserDataJobStatusEnum": "google.ads.googleads.v15.enums.types.offline_user_data_job_status", + "OfflineUserDataJobTypeEnum": "google.ads.googleads.v15.enums.types.offline_user_data_job_type", + "OperatingSystemVersionOperatorTypeEnum": "google.ads.googleads.v15.enums.types.operating_system_version_operator_type", + "OptimizationGoalTypeEnum": "google.ads.googleads.v15.enums.types.optimization_goal_type", + "ParentalStatusTypeEnum": "google.ads.googleads.v15.enums.types.parental_status_type", + "PaymentModeEnum": "google.ads.googleads.v15.enums.types.payment_mode", + "PerformanceMaxUpgradeStatusEnum": "google.ads.googleads.v15.enums.types.performance_max_upgrade_status", + "PlaceholderTypeEnum": "google.ads.googleads.v15.enums.types.placeholder_type", + "PlacementTypeEnum": "google.ads.googleads.v15.enums.types.placement_type", + "PolicyApprovalStatusEnum": "google.ads.googleads.v15.enums.types.policy_approval_status", + "PolicyReviewStatusEnum": "google.ads.googleads.v15.enums.types.policy_review_status", + "PolicyTopicEntryTypeEnum": "google.ads.googleads.v15.enums.types.policy_topic_entry_type", + "PolicyTopicEvidenceDestinationMismatchUrlTypeEnum": "google.ads.googleads.v15.enums.types.policy_topic_evidence_destination_mismatch_url_type", + "PolicyTopicEvidenceDestinationNotWorkingDeviceEnum": "google.ads.googleads.v15.enums.types.policy_topic_evidence_destination_not_working_device", + "PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum": "google.ads.googleads.v15.enums.types.policy_topic_evidence_destination_not_working_dns_error_type", + "PositiveGeoTargetTypeEnum": "google.ads.googleads.v15.enums.types.positive_geo_target_type", + "PriceExtensionPriceQualifierEnum": "google.ads.googleads.v15.enums.types.price_extension_price_qualifier", + "PriceExtensionPriceUnitEnum": "google.ads.googleads.v15.enums.types.price_extension_price_unit", + "PriceExtensionTypeEnum": "google.ads.googleads.v15.enums.types.price_extension_type", + "PricePlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.price_placeholder_field", + "ProductCategoryLevelEnum": "google.ads.googleads.v15.enums.types.product_category_level", + "ProductCategoryStateEnum": "google.ads.googleads.v15.enums.types.product_category_state", + "ProductChannelEnum": "google.ads.googleads.v15.enums.types.product_channel", + "ProductChannelExclusivityEnum": "google.ads.googleads.v15.enums.types.product_channel_exclusivity", + "ProductConditionEnum": "google.ads.googleads.v15.enums.types.product_condition", + "ProductCustomAttributeIndexEnum": "google.ads.googleads.v15.enums.types.product_custom_attribute_index", + "ProductLinkInvitationStatusEnum": "google.ads.googleads.v15.enums.types.product_link_invitation_status", + "ProductTypeLevelEnum": "google.ads.googleads.v15.enums.types.product_type_level", + "PromotionExtensionDiscountModifierEnum": "google.ads.googleads.v15.enums.types.promotion_extension_discount_modifier", + "PromotionExtensionOccasionEnum": "google.ads.googleads.v15.enums.types.promotion_extension_occasion", + "PromotionPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.promotion_placeholder_field", + "ProximityRadiusUnitsEnum": "google.ads.googleads.v15.enums.types.proximity_radius_units", + "QualityScoreBucketEnum": "google.ads.googleads.v15.enums.types.quality_score_bucket", + "ReachPlanAgeRangeEnum": "google.ads.googleads.v15.enums.types.reach_plan_age_range", + "ReachPlanNetworkEnum": "google.ads.googleads.v15.enums.types.reach_plan_network", + "ReachPlanSurfaceEnum": "google.ads.googleads.v15.enums.types.reach_plan_surface", + "RealEstatePlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.real_estate_placeholder_field", + "RecommendationSubscriptionStatusEnum": "google.ads.googleads.v15.enums.types.recommendation_subscription_status", + "RecommendationTypeEnum": "google.ads.googleads.v15.enums.types.recommendation_type", + "ResourceChangeOperationEnum": "google.ads.googleads.v15.enums.types.resource_change_operation", + "ResourceLimitTypeEnum": "google.ads.googleads.v15.enums.types.resource_limit_type", + "ResponseContentTypeEnum": "google.ads.googleads.v15.enums.types.response_content_type", + "SearchEngineResultsPageTypeEnum": "google.ads.googleads.v15.enums.types.search_engine_results_page_type", + "SearchTermMatchTypeEnum": "google.ads.googleads.v15.enums.types.search_term_match_type", + "SearchTermTargetingStatusEnum": "google.ads.googleads.v15.enums.types.search_term_targeting_status", + "SeasonalityEventScopeEnum": "google.ads.googleads.v15.enums.types.seasonality_event_scope", + "SeasonalityEventStatusEnum": "google.ads.googleads.v15.enums.types.seasonality_event_status", + "ServedAssetFieldTypeEnum": "google.ads.googleads.v15.enums.types.served_asset_field_type", + "SharedSetStatusEnum": "google.ads.googleads.v15.enums.types.shared_set_status", + "SharedSetTypeEnum": "google.ads.googleads.v15.enums.types.shared_set_type", + "ShoppingAddProductsToCampaignRecommendationEnum": "google.ads.googleads.v15.enums.types.shopping_add_products_to_campaign_recommendation_enum", + "SimulationModificationMethodEnum": "google.ads.googleads.v15.enums.types.simulation_modification_method", + "SimulationTypeEnum": "google.ads.googleads.v15.enums.types.simulation_type", + "SitelinkPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.sitelink_placeholder_field", + "SkAdNetworkAdEventTypeEnum": "google.ads.googleads.v15.enums.types.sk_ad_network_ad_event_type", + "SkAdNetworkAttributionCreditEnum": "google.ads.googleads.v15.enums.types.sk_ad_network_attribution_credit", + "SkAdNetworkCoarseConversionValueEnum": "google.ads.googleads.v15.enums.types.sk_ad_network_coarse_conversion_value", + "SkAdNetworkSourceTypeEnum": "google.ads.googleads.v15.enums.types.sk_ad_network_source_type", + "SkAdNetworkUserTypeEnum": "google.ads.googleads.v15.enums.types.sk_ad_network_user_type", + "SlotEnum": "google.ads.googleads.v15.enums.types.slot", + "SmartCampaignNotEligibleReasonEnum": "google.ads.googleads.v15.enums.types.smart_campaign_not_eligible_reason", + "SmartCampaignStatusEnum": "google.ads.googleads.v15.enums.types.smart_campaign_status", + "SpendingLimitTypeEnum": "google.ads.googleads.v15.enums.types.spending_limit_type", + "StructuredSnippetPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.structured_snippet_placeholder_field", + "SummaryRowSettingEnum": "google.ads.googleads.v15.enums.types.summary_row_setting", + "SystemManagedResourceSourceEnum": "google.ads.googleads.v15.enums.types.system_managed_entity_source", + "TargetCpaOptInRecommendationGoalEnum": "google.ads.googleads.v15.enums.types.target_cpa_opt_in_recommendation_goal", + "TargetFrequencyTimeUnitEnum": "google.ads.googleads.v15.enums.types.target_frequency_time_unit", + "TargetImpressionShareLocationEnum": "google.ads.googleads.v15.enums.types.target_impression_share_location", + "TargetingDimensionEnum": "google.ads.googleads.v15.enums.types.targeting_dimension", + "TimeTypeEnum": "google.ads.googleads.v15.enums.types.time_type", + "TrackingCodePageFormatEnum": "google.ads.googleads.v15.enums.types.tracking_code_page_format", + "TrackingCodeTypeEnum": "google.ads.googleads.v15.enums.types.tracking_code_type", + "TravelPlaceholderFieldEnum": "google.ads.googleads.v15.enums.types.travel_placeholder_field", + "UserIdentifierSourceEnum": "google.ads.googleads.v15.enums.types.user_identifier_source", + "UserInterestTaxonomyTypeEnum": "google.ads.googleads.v15.enums.types.user_interest_taxonomy_type", + "UserListAccessStatusEnum": "google.ads.googleads.v15.enums.types.user_list_access_status", + "UserListClosingReasonEnum": "google.ads.googleads.v15.enums.types.user_list_closing_reason", + "UserListCrmDataSourceTypeEnum": "google.ads.googleads.v15.enums.types.user_list_crm_data_source_type", + "UserListDateRuleItemOperatorEnum": "google.ads.googleads.v15.enums.types.user_list_date_rule_item_operator", + "UserListFlexibleRuleOperatorEnum": "google.ads.googleads.v15.enums.types.user_list_flexible_rule_operator", + "UserListLogicalRuleOperatorEnum": "google.ads.googleads.v15.enums.types.user_list_logical_rule_operator", + "UserListMembershipStatusEnum": "google.ads.googleads.v15.enums.types.user_list_membership_status", + "UserListNumberRuleItemOperatorEnum": "google.ads.googleads.v15.enums.types.user_list_number_rule_item_operator", + "UserListPrepopulationStatusEnum": "google.ads.googleads.v15.enums.types.user_list_prepopulation_status", + "UserListRuleTypeEnum": "google.ads.googleads.v15.enums.types.user_list_rule_type", + "UserListSizeRangeEnum": "google.ads.googleads.v15.enums.types.user_list_size_range", + "UserListStringRuleItemOperatorEnum": "google.ads.googleads.v15.enums.types.user_list_string_rule_item_operator", + "UserListTypeEnum": "google.ads.googleads.v15.enums.types.user_list_type", + "ValueRuleDeviceTypeEnum": "google.ads.googleads.v15.enums.types.value_rule_device_type", + "ValueRuleGeoLocationMatchTypeEnum": "google.ads.googleads.v15.enums.types.value_rule_geo_location_match_type", + "ValueRuleOperationEnum": "google.ads.googleads.v15.enums.types.value_rule_operation", + "ValueRuleSetAttachmentTypeEnum": "google.ads.googleads.v15.enums.types.value_rule_set_attachment_type", + "ValueRuleSetDimensionEnum": "google.ads.googleads.v15.enums.types.value_rule_set_dimension", + "VanityPharmaDisplayUrlModeEnum": "google.ads.googleads.v15.enums.types.vanity_pharma_display_url_mode", + "VanityPharmaTextEnum": "google.ads.googleads.v15.enums.types.vanity_pharma_text", + "VideoThumbnailEnum": "google.ads.googleads.v15.enums.types.video_thumbnail", + "WebpageConditionOperandEnum": "google.ads.googleads.v15.enums.types.webpage_condition_operand", + "WebpageConditionOperatorEnum": "google.ads.googleads.v15.enums.types.webpage_condition_operator", + "AccessInvitationErrorEnum": "google.ads.googleads.v15.errors.types.access_invitation_error", + "AccountBudgetProposalErrorEnum": "google.ads.googleads.v15.errors.types.account_budget_proposal_error", + "AccountLinkErrorEnum": "google.ads.googleads.v15.errors.types.account_link_error", + "AdCustomizerErrorEnum": "google.ads.googleads.v15.errors.types.ad_customizer_error", + "AdErrorEnum": "google.ads.googleads.v15.errors.types.ad_error", + "AdGroupAdErrorEnum": "google.ads.googleads.v15.errors.types.ad_group_ad_error", + "AdGroupBidModifierErrorEnum": "google.ads.googleads.v15.errors.types.ad_group_bid_modifier_error", + "AdGroupCriterionCustomizerErrorEnum": "google.ads.googleads.v15.errors.types.ad_group_criterion_customizer_error", + "AdGroupCriterionErrorEnum": "google.ads.googleads.v15.errors.types.ad_group_criterion_error", + "AdGroupCustomizerErrorEnum": "google.ads.googleads.v15.errors.types.ad_group_customizer_error", + "AdGroupErrorEnum": "google.ads.googleads.v15.errors.types.ad_group_error", + "AdGroupFeedErrorEnum": "google.ads.googleads.v15.errors.types.ad_group_feed_error", + "AdParameterErrorEnum": "google.ads.googleads.v15.errors.types.ad_parameter_error", + "AdSharingErrorEnum": "google.ads.googleads.v15.errors.types.ad_sharing_error", + "AdxErrorEnum": "google.ads.googleads.v15.errors.types.adx_error", + "AssetErrorEnum": "google.ads.googleads.v15.errors.types.asset_error", + "AssetGroupAssetErrorEnum": "google.ads.googleads.v15.errors.types.asset_group_asset_error", + "AssetGroupErrorEnum": "google.ads.googleads.v15.errors.types.asset_group_error", + "AssetGroupListingGroupFilterErrorEnum": "google.ads.googleads.v15.errors.types.asset_group_listing_group_filter_error", + "AssetGroupSignalErrorEnum": "google.ads.googleads.v15.errors.types.asset_group_signal_error", + "AssetLinkErrorEnum": "google.ads.googleads.v15.errors.types.asset_link_error", + "AssetSetAssetErrorEnum": "google.ads.googleads.v15.errors.types.asset_set_asset_error", + "AssetSetErrorEnum": "google.ads.googleads.v15.errors.types.asset_set_error", + "AssetSetLinkErrorEnum": "google.ads.googleads.v15.errors.types.asset_set_link_error", + "AudienceErrorEnum": "google.ads.googleads.v15.errors.types.audience_error", + "AudienceInsightsErrorEnum": "google.ads.googleads.v15.errors.types.audience_insights_error", + "AuthenticationErrorEnum": "google.ads.googleads.v15.errors.types.authentication_error", + "AuthorizationErrorEnum": "google.ads.googleads.v15.errors.types.authorization_error", + "BatchJobErrorEnum": "google.ads.googleads.v15.errors.types.batch_job_error", + "BiddingErrorEnum": "google.ads.googleads.v15.errors.types.bidding_error", + "BiddingStrategyErrorEnum": "google.ads.googleads.v15.errors.types.bidding_strategy_error", + "BillingSetupErrorEnum": "google.ads.googleads.v15.errors.types.billing_setup_error", + "CampaignBudgetErrorEnum": "google.ads.googleads.v15.errors.types.campaign_budget_error", + "CampaignConversionGoalErrorEnum": "google.ads.googleads.v15.errors.types.campaign_conversion_goal_error", + "CampaignCriterionErrorEnum": "google.ads.googleads.v15.errors.types.campaign_criterion_error", + "CampaignCustomizerErrorEnum": "google.ads.googleads.v15.errors.types.campaign_customizer_error", + "CampaignDraftErrorEnum": "google.ads.googleads.v15.errors.types.campaign_draft_error", + "CampaignErrorEnum": "google.ads.googleads.v15.errors.types.campaign_error", + "CampaignExperimentErrorEnum": "google.ads.googleads.v15.errors.types.campaign_experiment_error", + "CampaignFeedErrorEnum": "google.ads.googleads.v15.errors.types.campaign_feed_error", + "CampaignLifecycleGoalErrorEnum": "google.ads.googleads.v15.errors.types.campaign_lifecycle_goal_error", + "CampaignSharedSetErrorEnum": "google.ads.googleads.v15.errors.types.campaign_shared_set_error", + "ChangeEventErrorEnum": "google.ads.googleads.v15.errors.types.change_event_error", + "ChangeStatusErrorEnum": "google.ads.googleads.v15.errors.types.change_status_error", + "CollectionSizeErrorEnum": "google.ads.googleads.v15.errors.types.collection_size_error", + "ContextErrorEnum": "google.ads.googleads.v15.errors.types.context_error", + "ConversionActionErrorEnum": "google.ads.googleads.v15.errors.types.conversion_action_error", + "ConversionAdjustmentUploadErrorEnum": "google.ads.googleads.v15.errors.types.conversion_adjustment_upload_error", + "ConversionCustomVariableErrorEnum": "google.ads.googleads.v15.errors.types.conversion_custom_variable_error", + "ConversionGoalCampaignConfigErrorEnum": "google.ads.googleads.v15.errors.types.conversion_goal_campaign_config_error", + "ConversionUploadErrorEnum": "google.ads.googleads.v15.errors.types.conversion_upload_error", + "ConversionValueRuleErrorEnum": "google.ads.googleads.v15.errors.types.conversion_value_rule_error", + "ConversionValueRuleSetErrorEnum": "google.ads.googleads.v15.errors.types.conversion_value_rule_set_error", + "CountryCodeErrorEnum": "google.ads.googleads.v15.errors.types.country_code_error", + "CriterionErrorEnum": "google.ads.googleads.v15.errors.types.criterion_error", + "CurrencyCodeErrorEnum": "google.ads.googleads.v15.errors.types.currency_code_error", + "CurrencyErrorEnum": "google.ads.googleads.v15.errors.types.currency_error", + "CustomAudienceErrorEnum": "google.ads.googleads.v15.errors.types.custom_audience_error", + "CustomConversionGoalErrorEnum": "google.ads.googleads.v15.errors.types.custom_conversion_goal_error", + "CustomerClientLinkErrorEnum": "google.ads.googleads.v15.errors.types.customer_client_link_error", + "CustomerCustomizerErrorEnum": "google.ads.googleads.v15.errors.types.customer_customizer_error", + "CustomerErrorEnum": "google.ads.googleads.v15.errors.types.customer_error", + "CustomerFeedErrorEnum": "google.ads.googleads.v15.errors.types.customer_feed_error", + "CustomerLifecycleGoalErrorEnum": "google.ads.googleads.v15.errors.types.customer_lifecycle_goal_error", + "CustomerManagerLinkErrorEnum": "google.ads.googleads.v15.errors.types.customer_manager_link_error", + "CustomerSkAdNetworkConversionValueSchemaErrorEnum": "google.ads.googleads.v15.errors.types.customer_sk_ad_network_conversion_value_schema_error", + "CustomerUserAccessErrorEnum": "google.ads.googleads.v15.errors.types.customer_user_access_error", + "CustomInterestErrorEnum": "google.ads.googleads.v15.errors.types.custom_interest_error", + "CustomizerAttributeErrorEnum": "google.ads.googleads.v15.errors.types.customizer_attribute_error", + "DatabaseErrorEnum": "google.ads.googleads.v15.errors.types.database_error", + "DateErrorEnum": "google.ads.googleads.v15.errors.types.date_error", + "DateRangeErrorEnum": "google.ads.googleads.v15.errors.types.date_range_error", + "DistinctErrorEnum": "google.ads.googleads.v15.errors.types.distinct_error", + "EnumErrorEnum": "google.ads.googleads.v15.errors.types.enum_error", + "ErrorCode": "google.ads.googleads.v15.errors.types.errors", + "ErrorDetails": "google.ads.googleads.v15.errors.types.errors", + "ErrorLocation": "google.ads.googleads.v15.errors.types.errors", + "ExperimentArmErrorEnum": "google.ads.googleads.v15.errors.types.experiment_arm_error", + "ExperimentErrorEnum": "google.ads.googleads.v15.errors.types.experiment_error", + "ExtensionFeedItemErrorEnum": "google.ads.googleads.v15.errors.types.extension_feed_item_error", + "ExtensionSettingErrorEnum": "google.ads.googleads.v15.errors.types.extension_setting_error", + "FeedAttributeReferenceErrorEnum": "google.ads.googleads.v15.errors.types.feed_attribute_reference_error", + "FeedErrorEnum": "google.ads.googleads.v15.errors.types.feed_error", + "FeedItemErrorEnum": "google.ads.googleads.v15.errors.types.feed_item_error", + "FeedItemSetErrorEnum": "google.ads.googleads.v15.errors.types.feed_item_set_error", + "FeedItemSetLinkErrorEnum": "google.ads.googleads.v15.errors.types.feed_item_set_link_error", + "FeedItemTargetErrorEnum": "google.ads.googleads.v15.errors.types.feed_item_target_error", + "FeedItemValidationErrorEnum": "google.ads.googleads.v15.errors.types.feed_item_validation_error", + "FeedMappingErrorEnum": "google.ads.googleads.v15.errors.types.feed_mapping_error", + "FieldErrorEnum": "google.ads.googleads.v15.errors.types.field_error", + "FieldMaskErrorEnum": "google.ads.googleads.v15.errors.types.field_mask_error", + "FunctionErrorEnum": "google.ads.googleads.v15.errors.types.function_error", + "FunctionParsingErrorEnum": "google.ads.googleads.v15.errors.types.function_parsing_error", + "GeoTargetConstantSuggestionErrorEnum": "google.ads.googleads.v15.errors.types.geo_target_constant_suggestion_error", + "GoogleAdsError": "google.ads.googleads.v15.errors.types.errors", + "GoogleAdsFailure": "google.ads.googleads.v15.errors.types.errors", + "HeaderErrorEnum": "google.ads.googleads.v15.errors.types.header_error", + "IdErrorEnum": "google.ads.googleads.v15.errors.types.id_error", + "ImageErrorEnum": "google.ads.googleads.v15.errors.types.image_error", + "InternalErrorEnum": "google.ads.googleads.v15.errors.types.internal_error", + "InvoiceErrorEnum": "google.ads.googleads.v15.errors.types.invoice_error", + "KeywordPlanAdGroupErrorEnum": "google.ads.googleads.v15.errors.types.keyword_plan_ad_group_error", + "KeywordPlanAdGroupKeywordErrorEnum": "google.ads.googleads.v15.errors.types.keyword_plan_ad_group_keyword_error", + "KeywordPlanCampaignErrorEnum": "google.ads.googleads.v15.errors.types.keyword_plan_campaign_error", + "KeywordPlanCampaignKeywordErrorEnum": "google.ads.googleads.v15.errors.types.keyword_plan_campaign_keyword_error", + "KeywordPlanErrorEnum": "google.ads.googleads.v15.errors.types.keyword_plan_error", + "KeywordPlanIdeaErrorEnum": "google.ads.googleads.v15.errors.types.keyword_plan_idea_error", + "LabelErrorEnum": "google.ads.googleads.v15.errors.types.label_error", + "LanguageCodeErrorEnum": "google.ads.googleads.v15.errors.types.language_code_error", + "ListOperationErrorEnum": "google.ads.googleads.v15.errors.types.list_operation_error", + "ManagerLinkErrorEnum": "google.ads.googleads.v15.errors.types.manager_link_error", + "MediaBundleErrorEnum": "google.ads.googleads.v15.errors.types.media_bundle_error", + "MediaFileErrorEnum": "google.ads.googleads.v15.errors.types.media_file_error", + "MediaUploadErrorEnum": "google.ads.googleads.v15.errors.types.media_upload_error", + "MerchantCenterErrorEnum": "google.ads.googleads.v15.errors.types.merchant_center_error", + "MultiplierErrorEnum": "google.ads.googleads.v15.errors.types.multiplier_error", + "MutateErrorEnum": "google.ads.googleads.v15.errors.types.mutate_error", + "NewResourceCreationErrorEnum": "google.ads.googleads.v15.errors.types.new_resource_creation_error", + "NotAllowlistedErrorEnum": "google.ads.googleads.v15.errors.types.not_allowlisted_error", + "NotEmptyErrorEnum": "google.ads.googleads.v15.errors.types.not_empty_error", + "NullErrorEnum": "google.ads.googleads.v15.errors.types.null_error", + "OfflineUserDataJobErrorEnum": "google.ads.googleads.v15.errors.types.offline_user_data_job_error", + "OperationAccessDeniedErrorEnum": "google.ads.googleads.v15.errors.types.operation_access_denied_error", + "OperatorErrorEnum": "google.ads.googleads.v15.errors.types.operator_error", + "PartialFailureErrorEnum": "google.ads.googleads.v15.errors.types.partial_failure_error", + "PaymentsAccountErrorEnum": "google.ads.googleads.v15.errors.types.payments_account_error", + "PolicyFindingDetails": "google.ads.googleads.v15.errors.types.errors", + "PolicyFindingErrorEnum": "google.ads.googleads.v15.errors.types.policy_finding_error", + "PolicyValidationParameterErrorEnum": "google.ads.googleads.v15.errors.types.policy_validation_parameter_error", + "PolicyViolationDetails": "google.ads.googleads.v15.errors.types.errors", + "PolicyViolationErrorEnum": "google.ads.googleads.v15.errors.types.policy_violation_error", + "ProductLinkErrorEnum": "google.ads.googleads.v15.errors.types.product_link_error", + "ProductLinkInvitationErrorEnum": "google.ads.googleads.v15.errors.types.product_link_invitation_error", + "QueryErrorEnum": "google.ads.googleads.v15.errors.types.query_error", + "QuotaErrorDetails": "google.ads.googleads.v15.errors.types.errors", + "QuotaErrorEnum": "google.ads.googleads.v15.errors.types.quota_error", + "RangeErrorEnum": "google.ads.googleads.v15.errors.types.range_error", + "ReachPlanErrorEnum": "google.ads.googleads.v15.errors.types.reach_plan_error", + "RecommendationErrorEnum": "google.ads.googleads.v15.errors.types.recommendation_error", + "RecommendationSubscriptionErrorEnum": "google.ads.googleads.v15.errors.types.recommendation_subscription_error", + "RegionCodeErrorEnum": "google.ads.googleads.v15.errors.types.region_code_error", + "RequestErrorEnum": "google.ads.googleads.v15.errors.types.request_error", + "ResourceAccessDeniedErrorEnum": "google.ads.googleads.v15.errors.types.resource_access_denied_error", + "ResourceCountDetails": "google.ads.googleads.v15.errors.types.errors", + "ResourceCountLimitExceededErrorEnum": "google.ads.googleads.v15.errors.types.resource_count_limit_exceeded_error", + "SearchTermInsightErrorEnum": "google.ads.googleads.v15.errors.types.search_term_insight_error", + "SettingErrorEnum": "google.ads.googleads.v15.errors.types.setting_error", + "SharedCriterionErrorEnum": "google.ads.googleads.v15.errors.types.shared_criterion_error", + "SharedSetErrorEnum": "google.ads.googleads.v15.errors.types.shared_set_error", + "SizeLimitErrorEnum": "google.ads.googleads.v15.errors.types.size_limit_error", + "SmartCampaignErrorEnum": "google.ads.googleads.v15.errors.types.smart_campaign_error", + "StringFormatErrorEnum": "google.ads.googleads.v15.errors.types.string_format_error", + "StringLengthErrorEnum": "google.ads.googleads.v15.errors.types.string_length_error", + "ThirdPartyAppAnalyticsLinkErrorEnum": "google.ads.googleads.v15.errors.types.third_party_app_analytics_link_error", + "TimeZoneErrorEnum": "google.ads.googleads.v15.errors.types.time_zone_error", + "UrlFieldErrorEnum": "google.ads.googleads.v15.errors.types.url_field_error", + "UserDataErrorEnum": "google.ads.googleads.v15.errors.types.user_data_error", + "UserListErrorEnum": "google.ads.googleads.v15.errors.types.user_list_error", + "YoutubeVideoRegistrationErrorEnum": "google.ads.googleads.v15.errors.types.youtube_video_registration_error", + "AccessibleBiddingStrategy": "google.ads.googleads.v15.resources.types.accessible_bidding_strategy", + "AccountBudget": "google.ads.googleads.v15.resources.types.account_budget", + "AccountBudgetProposal": "google.ads.googleads.v15.resources.types.account_budget_proposal", + "AccountLink": "google.ads.googleads.v15.resources.types.account_link", + "Ad": "google.ads.googleads.v15.resources.types.ad", + "AdGroup": "google.ads.googleads.v15.resources.types.ad_group", + "AdGroupAd": "google.ads.googleads.v15.resources.types.ad_group_ad", + "AdGroupAdAssetCombinationView": "google.ads.googleads.v15.resources.types.ad_group_ad_asset_combination_view", + "AdGroupAdAssetPolicySummary": "google.ads.googleads.v15.resources.types.ad_group_ad_asset_view", + "AdGroupAdAssetView": "google.ads.googleads.v15.resources.types.ad_group_ad_asset_view", + "AdGroupAdLabel": "google.ads.googleads.v15.resources.types.ad_group_ad_label", + "AdGroupAdPolicySummary": "google.ads.googleads.v15.resources.types.ad_group_ad", + "AdGroupAsset": "google.ads.googleads.v15.resources.types.ad_group_asset", + "AdGroupAssetSet": "google.ads.googleads.v15.resources.types.ad_group_asset_set", + "AdGroupAudienceView": "google.ads.googleads.v15.resources.types.ad_group_audience_view", + "AdGroupBidModifier": "google.ads.googleads.v15.resources.types.ad_group_bid_modifier", + "AdGroupCriterion": "google.ads.googleads.v15.resources.types.ad_group_criterion", + "AdGroupCriterionCustomizer": "google.ads.googleads.v15.resources.types.ad_group_criterion_customizer", + "AdGroupCriterionLabel": "google.ads.googleads.v15.resources.types.ad_group_criterion_label", + "AdGroupCriterionSimulation": "google.ads.googleads.v15.resources.types.ad_group_criterion_simulation", + "AdGroupCustomizer": "google.ads.googleads.v15.resources.types.ad_group_customizer", + "AdGroupExtensionSetting": "google.ads.googleads.v15.resources.types.ad_group_extension_setting", + "AdGroupFeed": "google.ads.googleads.v15.resources.types.ad_group_feed", + "AdGroupLabel": "google.ads.googleads.v15.resources.types.ad_group_label", + "AdGroupSimulation": "google.ads.googleads.v15.resources.types.ad_group_simulation", + "AdParameter": "google.ads.googleads.v15.resources.types.ad_parameter", + "AdScheduleView": "google.ads.googleads.v15.resources.types.ad_schedule_view", + "AdvertisingPartnerLinkIdentifier": "google.ads.googleads.v15.resources.types.account_link", + "AgeRangeView": "google.ads.googleads.v15.resources.types.age_range_view", + "AndroidPrivacySharedKeyGoogleAdGroup": "google.ads.googleads.v15.resources.types.android_privacy_shared_key_google_ad_group", + "AndroidPrivacySharedKeyGoogleCampaign": "google.ads.googleads.v15.resources.types.android_privacy_shared_key_google_campaign", + "AndroidPrivacySharedKeyGoogleNetworkType": "google.ads.googleads.v15.resources.types.android_privacy_shared_key_google_network_type", + "Asset": "google.ads.googleads.v15.resources.types.asset", + "AssetFieldTypePolicySummary": "google.ads.googleads.v15.resources.types.asset", + "AssetFieldTypeView": "google.ads.googleads.v15.resources.types.asset_field_type_view", + "AssetGroup": "google.ads.googleads.v15.resources.types.asset_group", + "AssetGroupAsset": "google.ads.googleads.v15.resources.types.asset_group_asset", + "AssetGroupAssetCombinationData": "google.ads.googleads.v15.resources.types.asset_group_top_combination_view", + "AssetGroupListingGroupFilter": "google.ads.googleads.v15.resources.types.asset_group_listing_group_filter", + "AssetGroupProductGroupView": "google.ads.googleads.v15.resources.types.asset_group_product_group_view", + "AssetGroupSignal": "google.ads.googleads.v15.resources.types.asset_group_signal", + "AssetGroupTopCombinationView": "google.ads.googleads.v15.resources.types.asset_group_top_combination_view", + "AssetPolicySummary": "google.ads.googleads.v15.resources.types.asset", + "AssetSet": "google.ads.googleads.v15.resources.types.asset_set", + "AssetSetAsset": "google.ads.googleads.v15.resources.types.asset_set_asset", + "AssetSetTypeView": "google.ads.googleads.v15.resources.types.asset_set_type_view", + "AttributeFieldMapping": "google.ads.googleads.v15.resources.types.feed_mapping", + "Audience": "google.ads.googleads.v15.resources.types.audience", + "BackgroundCheckVerificationArtifact": "google.ads.googleads.v15.resources.types.local_services_verification_artifact", + "BatchJob": "google.ads.googleads.v15.resources.types.batch_job", + "BiddingDataExclusion": "google.ads.googleads.v15.resources.types.bidding_data_exclusion", + "BiddingSeasonalityAdjustment": "google.ads.googleads.v15.resources.types.bidding_seasonality_adjustment", + "BiddingStrategy": "google.ads.googleads.v15.resources.types.bidding_strategy", + "BiddingStrategySimulation": "google.ads.googleads.v15.resources.types.bidding_strategy_simulation", + "BillingSetup": "google.ads.googleads.v15.resources.types.billing_setup", + "CallReportingSetting": "google.ads.googleads.v15.resources.types.customer", + "CallView": "google.ads.googleads.v15.resources.types.call_view", + "Campaign": "google.ads.googleads.v15.resources.types.campaign", + "CampaignAsset": "google.ads.googleads.v15.resources.types.campaign_asset", + "CampaignAssetSet": "google.ads.googleads.v15.resources.types.campaign_asset_set", + "CampaignAudienceView": "google.ads.googleads.v15.resources.types.campaign_audience_view", + "CampaignBidModifier": "google.ads.googleads.v15.resources.types.campaign_bid_modifier", + "CampaignBudget": "google.ads.googleads.v15.resources.types.campaign_budget", + "CampaignConversionGoal": "google.ads.googleads.v15.resources.types.campaign_conversion_goal", + "CampaignCriterion": "google.ads.googleads.v15.resources.types.campaign_criterion", + "CampaignCustomizer": "google.ads.googleads.v15.resources.types.campaign_customizer", + "CampaignDraft": "google.ads.googleads.v15.resources.types.campaign_draft", + "CampaignExtensionSetting": "google.ads.googleads.v15.resources.types.campaign_extension_setting", + "CampaignFeed": "google.ads.googleads.v15.resources.types.campaign_feed", + "CampaignGroup": "google.ads.googleads.v15.resources.types.campaign_group", + "CampaignLabel": "google.ads.googleads.v15.resources.types.campaign_label", + "CampaignLifecycleGoal": "google.ads.googleads.v15.resources.types.campaign_lifecycle_goal", + "CampaignSearchTermInsight": "google.ads.googleads.v15.resources.types.campaign_search_term_insight", + "CampaignSharedSet": "google.ads.googleads.v15.resources.types.campaign_shared_set", + "CampaignSimulation": "google.ads.googleads.v15.resources.types.campaign_simulation", + "CarrierConstant": "google.ads.googleads.v15.resources.types.carrier_constant", + "ChangeEvent": "google.ads.googleads.v15.resources.types.change_event", + "ChangeStatus": "google.ads.googleads.v15.resources.types.change_status", + "ClickView": "google.ads.googleads.v15.resources.types.click_view", + "CombinedAudience": "google.ads.googleads.v15.resources.types.combined_audience", + "ContactDetails": "google.ads.googleads.v15.resources.types.local_services_lead", + "ConversionAction": "google.ads.googleads.v15.resources.types.conversion_action", + "ConversionCustomVariable": "google.ads.googleads.v15.resources.types.conversion_custom_variable", + "ConversionGoalCampaignConfig": "google.ads.googleads.v15.resources.types.conversion_goal_campaign_config", + "ConversionTrackingSetting": "google.ads.googleads.v15.resources.types.customer", + "ConversionValueRule": "google.ads.googleads.v15.resources.types.conversion_value_rule", + "ConversionValueRuleSet": "google.ads.googleads.v15.resources.types.conversion_value_rule_set", + "CurrencyConstant": "google.ads.googleads.v15.resources.types.currency_constant", + "CustomAudience": "google.ads.googleads.v15.resources.types.custom_audience", + "CustomAudienceMember": "google.ads.googleads.v15.resources.types.custom_audience", + "CustomConversionGoal": "google.ads.googleads.v15.resources.types.custom_conversion_goal", + "Customer": "google.ads.googleads.v15.resources.types.customer", + "CustomerAcquisitionGoalSettings": "google.ads.googleads.v15.resources.types.campaign_lifecycle_goal", + "CustomerAgreementSetting": "google.ads.googleads.v15.resources.types.customer", + "CustomerAsset": "google.ads.googleads.v15.resources.types.customer_asset", + "CustomerAssetSet": "google.ads.googleads.v15.resources.types.customer_asset_set", + "CustomerClient": "google.ads.googleads.v15.resources.types.customer_client", + "CustomerClientLink": "google.ads.googleads.v15.resources.types.customer_client_link", + "CustomerConversionGoal": "google.ads.googleads.v15.resources.types.customer_conversion_goal", + "CustomerCustomizer": "google.ads.googleads.v15.resources.types.customer_customizer", + "CustomerExtensionSetting": "google.ads.googleads.v15.resources.types.customer_extension_setting", + "CustomerFeed": "google.ads.googleads.v15.resources.types.customer_feed", + "CustomerLabel": "google.ads.googleads.v15.resources.types.customer_label", + "CustomerLifecycleGoal": "google.ads.googleads.v15.resources.types.customer_lifecycle_goal", + "CustomerManagerLink": "google.ads.googleads.v15.resources.types.customer_manager_link", + "CustomerNegativeCriterion": "google.ads.googleads.v15.resources.types.customer_negative_criterion", + "CustomerSearchTermInsight": "google.ads.googleads.v15.resources.types.customer_search_term_insight", + "CustomerSkAdNetworkConversionValueSchema": "google.ads.googleads.v15.resources.types.customer_sk_ad_network_conversion_value_schema", + "CustomerUserAccess": "google.ads.googleads.v15.resources.types.customer_user_access", + "CustomerUserAccessInvitation": "google.ads.googleads.v15.resources.types.customer_user_access_invitation", + "CustomInterest": "google.ads.googleads.v15.resources.types.custom_interest", + "CustomInterestMember": "google.ads.googleads.v15.resources.types.custom_interest", + "CustomizerAttribute": "google.ads.googleads.v15.resources.types.customizer_attribute", + "CustomLeadFormSubmissionField": "google.ads.googleads.v15.resources.types.lead_form_submission_data", + "DataPartnerIdentifier": "google.ads.googleads.v15.resources.types.product_link", + "DataPartnerLinkIdentifier": "google.ads.googleads.v15.resources.types.account_link", + "DetailedDemographic": "google.ads.googleads.v15.resources.types.detailed_demographic", + "DetailPlacementView": "google.ads.googleads.v15.resources.types.detail_placement_view", + "DisplayKeywordView": "google.ads.googleads.v15.resources.types.display_keyword_view", + "DistanceView": "google.ads.googleads.v15.resources.types.distance_view", + "DomainCategory": "google.ads.googleads.v15.resources.types.domain_category", + "DynamicSearchAdsSearchTermView": "google.ads.googleads.v15.resources.types.dynamic_search_ads_search_term_view", + "ExpandedLandingPageView": "google.ads.googleads.v15.resources.types.expanded_landing_page_view", + "Experiment": "google.ads.googleads.v15.resources.types.experiment", + "ExperimentArm": "google.ads.googleads.v15.resources.types.experiment_arm", + "ExtensionFeedItem": "google.ads.googleads.v15.resources.types.extension_feed_item", + "Feed": "google.ads.googleads.v15.resources.types.feed", + "FeedAttribute": "google.ads.googleads.v15.resources.types.feed", + "FeedAttributeOperation": "google.ads.googleads.v15.resources.types.feed", + "FeedItem": "google.ads.googleads.v15.resources.types.feed_item", + "FeedItemAttributeValue": "google.ads.googleads.v15.resources.types.feed_item", + "FeedItemPlaceholderPolicyInfo": "google.ads.googleads.v15.resources.types.feed_item", + "FeedItemSet": "google.ads.googleads.v15.resources.types.feed_item_set", + "FeedItemSetLink": "google.ads.googleads.v15.resources.types.feed_item_set_link", + "FeedItemTarget": "google.ads.googleads.v15.resources.types.feed_item_target", + "FeedItemValidationError": "google.ads.googleads.v15.resources.types.feed_item", + "FeedMapping": "google.ads.googleads.v15.resources.types.feed_mapping", + "FeedPlaceholderView": "google.ads.googleads.v15.resources.types.feed_placeholder_view", + "GenderView": "google.ads.googleads.v15.resources.types.gender_view", + "GeographicView": "google.ads.googleads.v15.resources.types.geographic_view", + "GeoTargetConstant": "google.ads.googleads.v15.resources.types.geo_target_constant", + "GoogleAdsField": "google.ads.googleads.v15.resources.types.google_ads_field", + "GoogleAdsIdentifier": "google.ads.googleads.v15.resources.types.product_link", + "GoogleAdsLinkIdentifier": "google.ads.googleads.v15.resources.types.account_link", + "GranularInsuranceStatus": "google.ads.googleads.v15.resources.types.customer", + "GranularLicenseStatus": "google.ads.googleads.v15.resources.types.customer", + "GroupPlacementView": "google.ads.googleads.v15.resources.types.group_placement_view", + "HotelCenterLinkInvitationIdentifier": "google.ads.googleads.v15.resources.types.product_link_invitation", + "HotelGroupView": "google.ads.googleads.v15.resources.types.hotel_group_view", + "HotelPerformanceView": "google.ads.googleads.v15.resources.types.hotel_performance_view", + "HotelReconciliation": "google.ads.googleads.v15.resources.types.hotel_reconciliation", + "IncomeRangeView": "google.ads.googleads.v15.resources.types.income_range_view", + "InsuranceVerificationArtifact": "google.ads.googleads.v15.resources.types.local_services_verification_artifact", + "Invoice": "google.ads.googleads.v15.resources.types.invoice", + "KeywordPlan": "google.ads.googleads.v15.resources.types.keyword_plan", + "KeywordPlanAdGroup": "google.ads.googleads.v15.resources.types.keyword_plan_ad_group", + "KeywordPlanAdGroupKeyword": "google.ads.googleads.v15.resources.types.keyword_plan_ad_group_keyword", + "KeywordPlanCampaign": "google.ads.googleads.v15.resources.types.keyword_plan_campaign", + "KeywordPlanCampaignKeyword": "google.ads.googleads.v15.resources.types.keyword_plan_campaign_keyword", + "KeywordPlanForecastPeriod": "google.ads.googleads.v15.resources.types.keyword_plan", + "KeywordPlanGeoTarget": "google.ads.googleads.v15.resources.types.keyword_plan_campaign", + "KeywordThemeConstant": "google.ads.googleads.v15.resources.types.keyword_theme_constant", + "KeywordView": "google.ads.googleads.v15.resources.types.keyword_view", + "Label": "google.ads.googleads.v15.resources.types.label", + "LandingPageView": "google.ads.googleads.v15.resources.types.landing_page_view", + "LanguageConstant": "google.ads.googleads.v15.resources.types.language_constant", + "LeadFormSubmissionData": "google.ads.googleads.v15.resources.types.lead_form_submission_data", + "LeadFormSubmissionField": "google.ads.googleads.v15.resources.types.lead_form_submission_data", + "LicenseVerificationArtifact": "google.ads.googleads.v15.resources.types.local_services_verification_artifact", + "LifeEvent": "google.ads.googleads.v15.resources.types.life_event", + "ListingGroupFilterDimension": "google.ads.googleads.v15.resources.types.asset_group_listing_group_filter", + "ListingGroupFilterDimensionPath": "google.ads.googleads.v15.resources.types.asset_group_listing_group_filter", + "LocalServicesLead": "google.ads.googleads.v15.resources.types.local_services_lead", + "LocalServicesLeadConversation": "google.ads.googleads.v15.resources.types.local_services_lead_conversation", + "LocalServicesSettings": "google.ads.googleads.v15.resources.types.customer", + "LocalServicesVerificationArtifact": "google.ads.googleads.v15.resources.types.local_services_verification_artifact", + "LocationView": "google.ads.googleads.v15.resources.types.location_view", + "ManagedPlacementView": "google.ads.googleads.v15.resources.types.managed_placement_view", + "MediaAudio": "google.ads.googleads.v15.resources.types.media_file", + "MediaBundle": "google.ads.googleads.v15.resources.types.media_file", + "MediaFile": "google.ads.googleads.v15.resources.types.media_file", + "MediaImage": "google.ads.googleads.v15.resources.types.media_file", + "MediaVideo": "google.ads.googleads.v15.resources.types.media_file", + "MerchantCenterIdentifier": "google.ads.googleads.v15.resources.types.product_link", + "MerchantCenterLinkInvitationIdentifier": "google.ads.googleads.v15.resources.types.product_link_invitation", + "MessageDetails": "google.ads.googleads.v15.resources.types.local_services_lead_conversation", + "MobileAppCategoryConstant": "google.ads.googleads.v15.resources.types.mobile_app_category_constant", + "MobileDeviceConstant": "google.ads.googleads.v15.resources.types.mobile_device_constant", + "Note": "google.ads.googleads.v15.resources.types.local_services_lead", + "OfflineConversionAlert": "google.ads.googleads.v15.resources.types.offline_conversion_upload_client_summary", + "OfflineConversionError": "google.ads.googleads.v15.resources.types.offline_conversion_upload_client_summary", + "OfflineConversionSummary": "google.ads.googleads.v15.resources.types.offline_conversion_upload_client_summary", + "OfflineConversionUploadClientSummary": "google.ads.googleads.v15.resources.types.offline_conversion_upload_client_summary", + "OfflineUserDataJob": "google.ads.googleads.v15.resources.types.offline_user_data_job", + "OfflineUserDataJobMetadata": "google.ads.googleads.v15.resources.types.offline_user_data_job", + "OperatingSystemVersionConstant": "google.ads.googleads.v15.resources.types.operating_system_version_constant", + "PaidOrganicSearchTermView": "google.ads.googleads.v15.resources.types.paid_organic_search_term_view", + "ParentalStatusView": "google.ads.googleads.v15.resources.types.parental_status_view", + "PaymentsAccount": "google.ads.googleads.v15.resources.types.payments_account", + "PerStoreView": "google.ads.googleads.v15.resources.types.per_store_view", + "PhoneCallDetails": "google.ads.googleads.v15.resources.types.local_services_lead_conversation", + "ProductCategoryConstant": "google.ads.googleads.v15.resources.types.product_category_constant", + "ProductGroupView": "google.ads.googleads.v15.resources.types.product_group_view", + "ProductLink": "google.ads.googleads.v15.resources.types.product_link", + "ProductLinkInvitation": "google.ads.googleads.v15.resources.types.product_link_invitation", + "QualifyingQuestion": "google.ads.googleads.v15.resources.types.qualifying_question", + "Recommendation": "google.ads.googleads.v15.resources.types.recommendation", + "RecommendationSubscription": "google.ads.googleads.v15.resources.types.recommendation_subscription", + "RemarketingAction": "google.ads.googleads.v15.resources.types.remarketing_action", + "RemarketingSetting": "google.ads.googleads.v15.resources.types.customer", + "SearchTermView": "google.ads.googleads.v15.resources.types.search_term_view", + "SharedCriterion": "google.ads.googleads.v15.resources.types.shared_criterion", + "SharedSet": "google.ads.googleads.v15.resources.types.shared_set", + "ShoppingPerformanceView": "google.ads.googleads.v15.resources.types.shopping_performance_view", + "SmartCampaignSearchTermView": "google.ads.googleads.v15.resources.types.smart_campaign_search_term_view", + "SmartCampaignSetting": "google.ads.googleads.v15.resources.types.smart_campaign_setting", + "ThirdPartyAppAnalyticsLink": "google.ads.googleads.v15.resources.types.third_party_app_analytics_link", + "ThirdPartyAppAnalyticsLinkIdentifier": "google.ads.googleads.v15.resources.types.account_link", + "TopicConstant": "google.ads.googleads.v15.resources.types.topic_constant", + "TopicView": "google.ads.googleads.v15.resources.types.topic_view", + "TravelActivityGroupView": "google.ads.googleads.v15.resources.types.travel_activity_group_view", + "TravelActivityPerformanceView": "google.ads.googleads.v15.resources.types.travel_activity_performance_view", + "UserInterest": "google.ads.googleads.v15.resources.types.user_interest", + "UserList": "google.ads.googleads.v15.resources.types.user_list", + "UserLocationView": "google.ads.googleads.v15.resources.types.user_location_view", + "Video": "google.ads.googleads.v15.resources.types.video", + "WebpageView": "google.ads.googleads.v15.resources.types.webpage_view", + "AccountBudgetProposalOperation": "google.ads.googleads.v15.services.types.account_budget_proposal_service", + "AccountLinkOperation": "google.ads.googleads.v15.services.types.account_link_service", + "AddBatchJobOperationsRequest": "google.ads.googleads.v15.services.types.batch_job_service", + "AddBatchJobOperationsResponse": "google.ads.googleads.v15.services.types.batch_job_service", + "AddOfflineUserDataJobOperationsRequest": "google.ads.googleads.v15.services.types.offline_user_data_job_service", + "AddOfflineUserDataJobOperationsResponse": "google.ads.googleads.v15.services.types.offline_user_data_job_service", + "AdGroupAdLabelOperation": "google.ads.googleads.v15.services.types.ad_group_ad_label_service", + "AdGroupAdOperation": "google.ads.googleads.v15.services.types.ad_group_ad_service", + "AdGroupAssetOperation": "google.ads.googleads.v15.services.types.ad_group_asset_service", + "AdGroupAssetSetOperation": "google.ads.googleads.v15.services.types.ad_group_asset_set_service", + "AdGroupBidModifierOperation": "google.ads.googleads.v15.services.types.ad_group_bid_modifier_service", + "AdGroupCriterionCustomizerOperation": "google.ads.googleads.v15.services.types.ad_group_criterion_customizer_service", + "AdGroupCriterionLabelOperation": "google.ads.googleads.v15.services.types.ad_group_criterion_label_service", + "AdGroupCriterionOperation": "google.ads.googleads.v15.services.types.ad_group_criterion_service", + "AdGroupCustomizerOperation": "google.ads.googleads.v15.services.types.ad_group_customizer_service", + "AdGroupExtensionSettingOperation": "google.ads.googleads.v15.services.types.ad_group_extension_setting_service", + "AdGroupFeedOperation": "google.ads.googleads.v15.services.types.ad_group_feed_service", + "AdGroupKeywordSuggestion": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "AdGroupLabelOperation": "google.ads.googleads.v15.services.types.ad_group_label_service", + "AdGroupOperation": "google.ads.googleads.v15.services.types.ad_group_service", + "AdOperation": "google.ads.googleads.v15.services.types.ad_service", + "AdParameterOperation": "google.ads.googleads.v15.services.types.ad_parameter_service", + "AdvancedProductTargeting": "google.ads.googleads.v15.services.types.reach_plan_service", + "ApplyRecommendationOperation": "google.ads.googleads.v15.services.types.recommendation_service", + "ApplyRecommendationRequest": "google.ads.googleads.v15.services.types.recommendation_service", + "ApplyRecommendationResponse": "google.ads.googleads.v15.services.types.recommendation_service", + "ApplyRecommendationResult": "google.ads.googleads.v15.services.types.recommendation_service", + "AssetGroupAssetOperation": "google.ads.googleads.v15.services.types.asset_group_asset_service", + "AssetGroupListingGroupFilterOperation": "google.ads.googleads.v15.services.types.asset_group_listing_group_filter_service", + "AssetGroupOperation": "google.ads.googleads.v15.services.types.asset_group_service", + "AssetGroupSignalOperation": "google.ads.googleads.v15.services.types.asset_group_signal_service", + "AssetOperation": "google.ads.googleads.v15.services.types.asset_service", + "AssetSetAssetOperation": "google.ads.googleads.v15.services.types.asset_set_asset_service", + "AssetSetOperation": "google.ads.googleads.v15.services.types.asset_set_service", + "AudienceCompositionAttribute": "google.ads.googleads.v15.services.types.audience_insights_service", + "AudienceCompositionAttributeCluster": "google.ads.googleads.v15.services.types.audience_insights_service", + "AudienceCompositionMetrics": "google.ads.googleads.v15.services.types.audience_insights_service", + "AudienceCompositionSection": "google.ads.googleads.v15.services.types.audience_insights_service", + "AudienceInsightsAttribute": "google.ads.googleads.v15.services.types.audience_insights_service", + "AudienceInsightsAttributeMetadata": "google.ads.googleads.v15.services.types.audience_insights_service", + "AudienceInsightsCategory": "google.ads.googleads.v15.services.types.audience_insights_service", + "AudienceInsightsDynamicLineup": "google.ads.googleads.v15.services.types.audience_insights_service", + "AudienceInsightsEntity": "google.ads.googleads.v15.services.types.audience_insights_service", + "AudienceInsightsTopic": "google.ads.googleads.v15.services.types.audience_insights_service", + "AudienceOperation": "google.ads.googleads.v15.services.types.audience_service", + "AudienceTargeting": "google.ads.googleads.v15.services.types.reach_plan_service", + "BasicInsightsAudience": "google.ads.googleads.v15.services.types.audience_insights_service", + "BatchJobOperation": "google.ads.googleads.v15.services.types.batch_job_service", + "BatchJobResult": "google.ads.googleads.v15.services.types.batch_job_service", + "BiddableKeyword": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "BiddingDataExclusionOperation": "google.ads.googleads.v15.services.types.bidding_data_exclusion_service", + "BiddingSeasonalityAdjustmentOperation": "google.ads.googleads.v15.services.types.bidding_seasonality_adjustment_service", + "BiddingStrategyOperation": "google.ads.googleads.v15.services.types.bidding_strategy_service", + "BillingSetupOperation": "google.ads.googleads.v15.services.types.billing_setup_service", + "BrandSuggestion": "google.ads.googleads.v15.services.types.brand_suggestion_service", + "CallConversion": "google.ads.googleads.v15.services.types.conversion_upload_service", + "CallConversionResult": "google.ads.googleads.v15.services.types.conversion_upload_service", + "CampaignAssetOperation": "google.ads.googleads.v15.services.types.campaign_asset_service", + "CampaignAssetSetOperation": "google.ads.googleads.v15.services.types.campaign_asset_set_service", + "CampaignBidModifierOperation": "google.ads.googleads.v15.services.types.campaign_bid_modifier_service", + "CampaignBudgetMapping": "google.ads.googleads.v15.services.types.experiment_service", + "CampaignBudgetOperation": "google.ads.googleads.v15.services.types.campaign_budget_service", + "CampaignConversionGoalOperation": "google.ads.googleads.v15.services.types.campaign_conversion_goal_service", + "CampaignCriterionOperation": "google.ads.googleads.v15.services.types.campaign_criterion_service", + "CampaignCustomizerOperation": "google.ads.googleads.v15.services.types.campaign_customizer_service", + "CampaignDraftOperation": "google.ads.googleads.v15.services.types.campaign_draft_service", + "CampaignDuration": "google.ads.googleads.v15.services.types.reach_plan_service", + "CampaignExtensionSettingOperation": "google.ads.googleads.v15.services.types.campaign_extension_setting_service", + "CampaignFeedOperation": "google.ads.googleads.v15.services.types.campaign_feed_service", + "CampaignGroupOperation": "google.ads.googleads.v15.services.types.campaign_group_service", + "CampaignLabelOperation": "google.ads.googleads.v15.services.types.campaign_label_service", + "CampaignLifecycleGoalOperation": "google.ads.googleads.v15.services.types.campaign_lifecycle_goal_service", + "CampaignOperation": "google.ads.googleads.v15.services.types.campaign_service", + "CampaignSharedSetOperation": "google.ads.googleads.v15.services.types.campaign_shared_set_service", + "CampaignToForecast": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "CartData": "google.ads.googleads.v15.services.types.conversion_upload_service", + "ClickConversion": "google.ads.googleads.v15.services.types.conversion_upload_service", + "ClickConversionResult": "google.ads.googleads.v15.services.types.conversion_upload_service", + "ConfigureCampaignLifecycleGoalsRequest": "google.ads.googleads.v15.services.types.campaign_lifecycle_goal_service", + "ConfigureCampaignLifecycleGoalsResponse": "google.ads.googleads.v15.services.types.campaign_lifecycle_goal_service", + "ConfigureCampaignLifecycleGoalsResult": "google.ads.googleads.v15.services.types.campaign_lifecycle_goal_service", + "ConfigureCustomerLifecycleGoalsRequest": "google.ads.googleads.v15.services.types.customer_lifecycle_goal_service", + "ConfigureCustomerLifecycleGoalsResponse": "google.ads.googleads.v15.services.types.customer_lifecycle_goal_service", + "ConfigureCustomerLifecycleGoalsResult": "google.ads.googleads.v15.services.types.customer_lifecycle_goal_service", + "ConversionActionOperation": "google.ads.googleads.v15.services.types.conversion_action_service", + "ConversionAdjustment": "google.ads.googleads.v15.services.types.conversion_adjustment_upload_service", + "ConversionAdjustmentResult": "google.ads.googleads.v15.services.types.conversion_adjustment_upload_service", + "ConversionCustomVariableOperation": "google.ads.googleads.v15.services.types.conversion_custom_variable_service", + "ConversionGoalCampaignConfigOperation": "google.ads.googleads.v15.services.types.conversion_goal_campaign_config_service", + "ConversionValueRuleOperation": "google.ads.googleads.v15.services.types.conversion_value_rule_service", + "ConversionValueRuleSetOperation": "google.ads.googleads.v15.services.types.conversion_value_rule_set_service", + "CreateAccountLinkRequest": "google.ads.googleads.v15.services.types.account_link_service", + "CreateAccountLinkResponse": "google.ads.googleads.v15.services.types.account_link_service", + "CreateCustomerClientRequest": "google.ads.googleads.v15.services.types.customer_service", + "CreateCustomerClientResponse": "google.ads.googleads.v15.services.types.customer_service", + "CreateOfflineUserDataJobRequest": "google.ads.googleads.v15.services.types.offline_user_data_job_service", + "CreateOfflineUserDataJobResponse": "google.ads.googleads.v15.services.types.offline_user_data_job_service", + "CreateProductLinkRequest": "google.ads.googleads.v15.services.types.product_link_service", + "CreateProductLinkResponse": "google.ads.googleads.v15.services.types.product_link_service", + "CriterionBidModifier": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "CustomAudienceOperation": "google.ads.googleads.v15.services.types.custom_audience_service", + "CustomConversionGoalOperation": "google.ads.googleads.v15.services.types.custom_conversion_goal_service", + "CustomerAssetOperation": "google.ads.googleads.v15.services.types.customer_asset_service", + "CustomerAssetSetOperation": "google.ads.googleads.v15.services.types.customer_asset_set_service", + "CustomerClientLinkOperation": "google.ads.googleads.v15.services.types.customer_client_link_service", + "CustomerConversionGoalOperation": "google.ads.googleads.v15.services.types.customer_conversion_goal_service", + "CustomerCustomizerOperation": "google.ads.googleads.v15.services.types.customer_customizer_service", + "CustomerExtensionSettingOperation": "google.ads.googleads.v15.services.types.customer_extension_setting_service", + "CustomerFeedOperation": "google.ads.googleads.v15.services.types.customer_feed_service", + "CustomerLabelOperation": "google.ads.googleads.v15.services.types.customer_label_service", + "CustomerLifecycleGoalOperation": "google.ads.googleads.v15.services.types.customer_lifecycle_goal_service", + "CustomerManagerLinkOperation": "google.ads.googleads.v15.services.types.customer_manager_link_service", + "CustomerNegativeCriterionOperation": "google.ads.googleads.v15.services.types.customer_negative_criterion_service", + "CustomerOperation": "google.ads.googleads.v15.services.types.customer_service", + "CustomerSkAdNetworkConversionValueSchemaOperation": "google.ads.googleads.v15.services.types.customer_sk_ad_network_conversion_value_schema_service", + "CustomerUserAccessInvitationOperation": "google.ads.googleads.v15.services.types.customer_user_access_invitation_service", + "CustomerUserAccessOperation": "google.ads.googleads.v15.services.types.customer_user_access_service", + "CustomInterestOperation": "google.ads.googleads.v15.services.types.custom_interest_service", + "CustomizerAttributeOperation": "google.ads.googleads.v15.services.types.customizer_attribute_service", + "CustomVariable": "google.ads.googleads.v15.services.types.conversion_upload_service", + "DismissRecommendationRequest": "google.ads.googleads.v15.services.types.recommendation_service", + "DismissRecommendationResponse": "google.ads.googleads.v15.services.types.recommendation_service", + "DynamicLineupAttributeMetadata": "google.ads.googleads.v15.services.types.audience_insights_service", + "EffectiveFrequencyBreakdown": "google.ads.googleads.v15.services.types.reach_plan_service", + "EffectiveFrequencyLimit": "google.ads.googleads.v15.services.types.reach_plan_service", + "EndExperimentRequest": "google.ads.googleads.v15.services.types.experiment_service", + "ExperimentArmOperation": "google.ads.googleads.v15.services.types.experiment_arm_service", + "ExperimentOperation": "google.ads.googleads.v15.services.types.experiment_service", + "ExtensionFeedItemOperation": "google.ads.googleads.v15.services.types.extension_feed_item_service", + "ExternalAttributionData": "google.ads.googleads.v15.services.types.conversion_upload_service", + "FeedItemOperation": "google.ads.googleads.v15.services.types.feed_item_service", + "FeedItemSetLinkOperation": "google.ads.googleads.v15.services.types.feed_item_set_link_service", + "FeedItemSetOperation": "google.ads.googleads.v15.services.types.feed_item_set_service", + "FeedItemTargetOperation": "google.ads.googleads.v15.services.types.feed_item_target_service", + "FeedMappingOperation": "google.ads.googleads.v15.services.types.feed_mapping_service", + "FeedOperation": "google.ads.googleads.v15.services.types.feed_service", + "Forecast": "google.ads.googleads.v15.services.types.reach_plan_service", + "ForecastAdGroup": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "ForecastMetricOptions": "google.ads.googleads.v15.services.types.reach_plan_service", + "FrequencyCap": "google.ads.googleads.v15.services.types.reach_plan_service", + "GclidDateTimePair": "google.ads.googleads.v15.services.types.conversion_adjustment_upload_service", + "GenerateAdGroupThemesRequest": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "GenerateAdGroupThemesResponse": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "GenerateAudienceCompositionInsightsRequest": "google.ads.googleads.v15.services.types.audience_insights_service", + "GenerateAudienceCompositionInsightsResponse": "google.ads.googleads.v15.services.types.audience_insights_service", + "GenerateInsightsFinderReportRequest": "google.ads.googleads.v15.services.types.audience_insights_service", + "GenerateInsightsFinderReportResponse": "google.ads.googleads.v15.services.types.audience_insights_service", + "GenerateKeywordForecastMetricsRequest": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "GenerateKeywordForecastMetricsResponse": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "GenerateKeywordHistoricalMetricsRequest": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "GenerateKeywordHistoricalMetricsResponse": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "GenerateKeywordHistoricalMetricsResult": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "GenerateKeywordIdeaResponse": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "GenerateKeywordIdeaResult": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "GenerateKeywordIdeasRequest": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "GenerateReachForecastRequest": "google.ads.googleads.v15.services.types.reach_plan_service", + "GenerateReachForecastResponse": "google.ads.googleads.v15.services.types.reach_plan_service", + "GenerateSuggestedTargetingInsightsRequest": "google.ads.googleads.v15.services.types.audience_insights_service", + "GenerateSuggestedTargetingInsightsResponse": "google.ads.googleads.v15.services.types.audience_insights_service", + "GeoTargetConstantSuggestion": "google.ads.googleads.v15.services.types.geo_target_constant_service", + "GetAdRequest": "google.ads.googleads.v15.services.types.ad_service", + "GetGoogleAdsFieldRequest": "google.ads.googleads.v15.services.types.google_ads_field_service", + "GetSmartCampaignStatusRequest": "google.ads.googleads.v15.services.types.smart_campaign_setting_service", + "GetSmartCampaignStatusResponse": "google.ads.googleads.v15.services.types.smart_campaign_setting_service", + "GoogleAdsRow": "google.ads.googleads.v15.services.types.google_ads_service", + "GraduateExperimentRequest": "google.ads.googleads.v15.services.types.experiment_service", + "HotelAssetSuggestion": "google.ads.googleads.v15.services.types.travel_asset_suggestion_service", + "HotelImageAsset": "google.ads.googleads.v15.services.types.travel_asset_suggestion_service", + "HotelTextAsset": "google.ads.googleads.v15.services.types.travel_asset_suggestion_service", + "InsightsAudience": "google.ads.googleads.v15.services.types.audience_insights_service", + "InsightsAudienceAttributeGroup": "google.ads.googleads.v15.services.types.audience_insights_service", + "KeywordAndUrlSeed": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "KeywordForecastMetrics": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "KeywordPlanAdGroupKeywordOperation": "google.ads.googleads.v15.services.types.keyword_plan_ad_group_keyword_service", + "KeywordPlanAdGroupOperation": "google.ads.googleads.v15.services.types.keyword_plan_ad_group_service", + "KeywordPlanCampaignKeywordOperation": "google.ads.googleads.v15.services.types.keyword_plan_campaign_keyword_service", + "KeywordPlanCampaignOperation": "google.ads.googleads.v15.services.types.keyword_plan_campaign_service", + "KeywordPlanOperation": "google.ads.googleads.v15.services.types.keyword_plan_service", + "KeywordSeed": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "LabelOperation": "google.ads.googleads.v15.services.types.label_service", + "ListAccessibleCustomersRequest": "google.ads.googleads.v15.services.types.customer_service", + "ListAccessibleCustomersResponse": "google.ads.googleads.v15.services.types.customer_service", + "ListAudienceInsightsAttributesRequest": "google.ads.googleads.v15.services.types.audience_insights_service", + "ListAudienceInsightsAttributesResponse": "google.ads.googleads.v15.services.types.audience_insights_service", + "ListBatchJobResultsRequest": "google.ads.googleads.v15.services.types.batch_job_service", + "ListBatchJobResultsResponse": "google.ads.googleads.v15.services.types.batch_job_service", + "ListCampaignDraftAsyncErrorsRequest": "google.ads.googleads.v15.services.types.campaign_draft_service", + "ListCampaignDraftAsyncErrorsResponse": "google.ads.googleads.v15.services.types.campaign_draft_service", + "ListExperimentAsyncErrorsRequest": "google.ads.googleads.v15.services.types.experiment_service", + "ListExperimentAsyncErrorsResponse": "google.ads.googleads.v15.services.types.experiment_service", + "ListInsightsEligibleDatesRequest": "google.ads.googleads.v15.services.types.audience_insights_service", + "ListInsightsEligibleDatesResponse": "google.ads.googleads.v15.services.types.audience_insights_service", + "ListInvoicesRequest": "google.ads.googleads.v15.services.types.invoice_service", + "ListInvoicesResponse": "google.ads.googleads.v15.services.types.invoice_service", + "ListPaymentsAccountsRequest": "google.ads.googleads.v15.services.types.payments_account_service", + "ListPaymentsAccountsResponse": "google.ads.googleads.v15.services.types.payments_account_service", + "ListPlannableLocationsRequest": "google.ads.googleads.v15.services.types.reach_plan_service", + "ListPlannableLocationsResponse": "google.ads.googleads.v15.services.types.reach_plan_service", + "ListPlannableProductsRequest": "google.ads.googleads.v15.services.types.reach_plan_service", + "ListPlannableProductsResponse": "google.ads.googleads.v15.services.types.reach_plan_service", + "LocationAttributeMetadata": "google.ads.googleads.v15.services.types.audience_insights_service", + "ManualCpcBiddingStrategy": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "MaximizeClicksBiddingStrategy": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "MaximizeConversionsBiddingStrategy": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "MoveManagerLinkRequest": "google.ads.googleads.v15.services.types.customer_manager_link_service", + "MoveManagerLinkResponse": "google.ads.googleads.v15.services.types.customer_manager_link_service", + "MutateAccountBudgetProposalRequest": "google.ads.googleads.v15.services.types.account_budget_proposal_service", + "MutateAccountBudgetProposalResponse": "google.ads.googleads.v15.services.types.account_budget_proposal_service", + "MutateAccountBudgetProposalResult": "google.ads.googleads.v15.services.types.account_budget_proposal_service", + "MutateAccountLinkRequest": "google.ads.googleads.v15.services.types.account_link_service", + "MutateAccountLinkResponse": "google.ads.googleads.v15.services.types.account_link_service", + "MutateAccountLinkResult": "google.ads.googleads.v15.services.types.account_link_service", + "MutateAdGroupAdLabelResult": "google.ads.googleads.v15.services.types.ad_group_ad_label_service", + "MutateAdGroupAdLabelsRequest": "google.ads.googleads.v15.services.types.ad_group_ad_label_service", + "MutateAdGroupAdLabelsResponse": "google.ads.googleads.v15.services.types.ad_group_ad_label_service", + "MutateAdGroupAdResult": "google.ads.googleads.v15.services.types.ad_group_ad_service", + "MutateAdGroupAdsRequest": "google.ads.googleads.v15.services.types.ad_group_ad_service", + "MutateAdGroupAdsResponse": "google.ads.googleads.v15.services.types.ad_group_ad_service", + "MutateAdGroupAssetResult": "google.ads.googleads.v15.services.types.ad_group_asset_service", + "MutateAdGroupAssetSetResult": "google.ads.googleads.v15.services.types.ad_group_asset_set_service", + "MutateAdGroupAssetSetsRequest": "google.ads.googleads.v15.services.types.ad_group_asset_set_service", + "MutateAdGroupAssetSetsResponse": "google.ads.googleads.v15.services.types.ad_group_asset_set_service", + "MutateAdGroupAssetsRequest": "google.ads.googleads.v15.services.types.ad_group_asset_service", + "MutateAdGroupAssetsResponse": "google.ads.googleads.v15.services.types.ad_group_asset_service", + "MutateAdGroupBidModifierResult": "google.ads.googleads.v15.services.types.ad_group_bid_modifier_service", + "MutateAdGroupBidModifiersRequest": "google.ads.googleads.v15.services.types.ad_group_bid_modifier_service", + "MutateAdGroupBidModifiersResponse": "google.ads.googleads.v15.services.types.ad_group_bid_modifier_service", + "MutateAdGroupCriteriaRequest": "google.ads.googleads.v15.services.types.ad_group_criterion_service", + "MutateAdGroupCriteriaResponse": "google.ads.googleads.v15.services.types.ad_group_criterion_service", + "MutateAdGroupCriterionCustomizerResult": "google.ads.googleads.v15.services.types.ad_group_criterion_customizer_service", + "MutateAdGroupCriterionCustomizersRequest": "google.ads.googleads.v15.services.types.ad_group_criterion_customizer_service", + "MutateAdGroupCriterionCustomizersResponse": "google.ads.googleads.v15.services.types.ad_group_criterion_customizer_service", + "MutateAdGroupCriterionLabelResult": "google.ads.googleads.v15.services.types.ad_group_criterion_label_service", + "MutateAdGroupCriterionLabelsRequest": "google.ads.googleads.v15.services.types.ad_group_criterion_label_service", + "MutateAdGroupCriterionLabelsResponse": "google.ads.googleads.v15.services.types.ad_group_criterion_label_service", + "MutateAdGroupCriterionResult": "google.ads.googleads.v15.services.types.ad_group_criterion_service", + "MutateAdGroupCustomizerResult": "google.ads.googleads.v15.services.types.ad_group_customizer_service", + "MutateAdGroupCustomizersRequest": "google.ads.googleads.v15.services.types.ad_group_customizer_service", + "MutateAdGroupCustomizersResponse": "google.ads.googleads.v15.services.types.ad_group_customizer_service", + "MutateAdGroupExtensionSettingResult": "google.ads.googleads.v15.services.types.ad_group_extension_setting_service", + "MutateAdGroupExtensionSettingsRequest": "google.ads.googleads.v15.services.types.ad_group_extension_setting_service", + "MutateAdGroupExtensionSettingsResponse": "google.ads.googleads.v15.services.types.ad_group_extension_setting_service", + "MutateAdGroupFeedResult": "google.ads.googleads.v15.services.types.ad_group_feed_service", + "MutateAdGroupFeedsRequest": "google.ads.googleads.v15.services.types.ad_group_feed_service", + "MutateAdGroupFeedsResponse": "google.ads.googleads.v15.services.types.ad_group_feed_service", + "MutateAdGroupLabelResult": "google.ads.googleads.v15.services.types.ad_group_label_service", + "MutateAdGroupLabelsRequest": "google.ads.googleads.v15.services.types.ad_group_label_service", + "MutateAdGroupLabelsResponse": "google.ads.googleads.v15.services.types.ad_group_label_service", + "MutateAdGroupResult": "google.ads.googleads.v15.services.types.ad_group_service", + "MutateAdGroupsRequest": "google.ads.googleads.v15.services.types.ad_group_service", + "MutateAdGroupsResponse": "google.ads.googleads.v15.services.types.ad_group_service", + "MutateAdParameterResult": "google.ads.googleads.v15.services.types.ad_parameter_service", + "MutateAdParametersRequest": "google.ads.googleads.v15.services.types.ad_parameter_service", + "MutateAdParametersResponse": "google.ads.googleads.v15.services.types.ad_parameter_service", + "MutateAdResult": "google.ads.googleads.v15.services.types.ad_service", + "MutateAdsRequest": "google.ads.googleads.v15.services.types.ad_service", + "MutateAdsResponse": "google.ads.googleads.v15.services.types.ad_service", + "MutateAssetGroupAssetResult": "google.ads.googleads.v15.services.types.asset_group_asset_service", + "MutateAssetGroupAssetsRequest": "google.ads.googleads.v15.services.types.asset_group_asset_service", + "MutateAssetGroupAssetsResponse": "google.ads.googleads.v15.services.types.asset_group_asset_service", + "MutateAssetGroupListingGroupFilterResult": "google.ads.googleads.v15.services.types.asset_group_listing_group_filter_service", + "MutateAssetGroupListingGroupFiltersRequest": "google.ads.googleads.v15.services.types.asset_group_listing_group_filter_service", + "MutateAssetGroupListingGroupFiltersResponse": "google.ads.googleads.v15.services.types.asset_group_listing_group_filter_service", + "MutateAssetGroupResult": "google.ads.googleads.v15.services.types.asset_group_service", + "MutateAssetGroupSignalResult": "google.ads.googleads.v15.services.types.asset_group_signal_service", + "MutateAssetGroupSignalsRequest": "google.ads.googleads.v15.services.types.asset_group_signal_service", + "MutateAssetGroupSignalsResponse": "google.ads.googleads.v15.services.types.asset_group_signal_service", + "MutateAssetGroupsRequest": "google.ads.googleads.v15.services.types.asset_group_service", + "MutateAssetGroupsResponse": "google.ads.googleads.v15.services.types.asset_group_service", + "MutateAssetResult": "google.ads.googleads.v15.services.types.asset_service", + "MutateAssetSetAssetResult": "google.ads.googleads.v15.services.types.asset_set_asset_service", + "MutateAssetSetAssetsRequest": "google.ads.googleads.v15.services.types.asset_set_asset_service", + "MutateAssetSetAssetsResponse": "google.ads.googleads.v15.services.types.asset_set_asset_service", + "MutateAssetSetResult": "google.ads.googleads.v15.services.types.asset_set_service", + "MutateAssetSetsRequest": "google.ads.googleads.v15.services.types.asset_set_service", + "MutateAssetSetsResponse": "google.ads.googleads.v15.services.types.asset_set_service", + "MutateAssetsRequest": "google.ads.googleads.v15.services.types.asset_service", + "MutateAssetsResponse": "google.ads.googleads.v15.services.types.asset_service", + "MutateAudienceResult": "google.ads.googleads.v15.services.types.audience_service", + "MutateAudiencesRequest": "google.ads.googleads.v15.services.types.audience_service", + "MutateAudiencesResponse": "google.ads.googleads.v15.services.types.audience_service", + "MutateBatchJobRequest": "google.ads.googleads.v15.services.types.batch_job_service", + "MutateBatchJobResponse": "google.ads.googleads.v15.services.types.batch_job_service", + "MutateBatchJobResult": "google.ads.googleads.v15.services.types.batch_job_service", + "MutateBiddingDataExclusionsRequest": "google.ads.googleads.v15.services.types.bidding_data_exclusion_service", + "MutateBiddingDataExclusionsResponse": "google.ads.googleads.v15.services.types.bidding_data_exclusion_service", + "MutateBiddingDataExclusionsResult": "google.ads.googleads.v15.services.types.bidding_data_exclusion_service", + "MutateBiddingSeasonalityAdjustmentsRequest": "google.ads.googleads.v15.services.types.bidding_seasonality_adjustment_service", + "MutateBiddingSeasonalityAdjustmentsResponse": "google.ads.googleads.v15.services.types.bidding_seasonality_adjustment_service", + "MutateBiddingSeasonalityAdjustmentsResult": "google.ads.googleads.v15.services.types.bidding_seasonality_adjustment_service", + "MutateBiddingStrategiesRequest": "google.ads.googleads.v15.services.types.bidding_strategy_service", + "MutateBiddingStrategiesResponse": "google.ads.googleads.v15.services.types.bidding_strategy_service", + "MutateBiddingStrategyResult": "google.ads.googleads.v15.services.types.bidding_strategy_service", + "MutateBillingSetupRequest": "google.ads.googleads.v15.services.types.billing_setup_service", + "MutateBillingSetupResponse": "google.ads.googleads.v15.services.types.billing_setup_service", + "MutateBillingSetupResult": "google.ads.googleads.v15.services.types.billing_setup_service", + "MutateCampaignAssetResult": "google.ads.googleads.v15.services.types.campaign_asset_service", + "MutateCampaignAssetSetResult": "google.ads.googleads.v15.services.types.campaign_asset_set_service", + "MutateCampaignAssetSetsRequest": "google.ads.googleads.v15.services.types.campaign_asset_set_service", + "MutateCampaignAssetSetsResponse": "google.ads.googleads.v15.services.types.campaign_asset_set_service", + "MutateCampaignAssetsRequest": "google.ads.googleads.v15.services.types.campaign_asset_service", + "MutateCampaignAssetsResponse": "google.ads.googleads.v15.services.types.campaign_asset_service", + "MutateCampaignBidModifierResult": "google.ads.googleads.v15.services.types.campaign_bid_modifier_service", + "MutateCampaignBidModifiersRequest": "google.ads.googleads.v15.services.types.campaign_bid_modifier_service", + "MutateCampaignBidModifiersResponse": "google.ads.googleads.v15.services.types.campaign_bid_modifier_service", + "MutateCampaignBudgetResult": "google.ads.googleads.v15.services.types.campaign_budget_service", + "MutateCampaignBudgetsRequest": "google.ads.googleads.v15.services.types.campaign_budget_service", + "MutateCampaignBudgetsResponse": "google.ads.googleads.v15.services.types.campaign_budget_service", + "MutateCampaignConversionGoalResult": "google.ads.googleads.v15.services.types.campaign_conversion_goal_service", + "MutateCampaignConversionGoalsRequest": "google.ads.googleads.v15.services.types.campaign_conversion_goal_service", + "MutateCampaignConversionGoalsResponse": "google.ads.googleads.v15.services.types.campaign_conversion_goal_service", + "MutateCampaignCriteriaRequest": "google.ads.googleads.v15.services.types.campaign_criterion_service", + "MutateCampaignCriteriaResponse": "google.ads.googleads.v15.services.types.campaign_criterion_service", + "MutateCampaignCriterionResult": "google.ads.googleads.v15.services.types.campaign_criterion_service", + "MutateCampaignCustomizerResult": "google.ads.googleads.v15.services.types.campaign_customizer_service", + "MutateCampaignCustomizersRequest": "google.ads.googleads.v15.services.types.campaign_customizer_service", + "MutateCampaignCustomizersResponse": "google.ads.googleads.v15.services.types.campaign_customizer_service", + "MutateCampaignDraftResult": "google.ads.googleads.v15.services.types.campaign_draft_service", + "MutateCampaignDraftsRequest": "google.ads.googleads.v15.services.types.campaign_draft_service", + "MutateCampaignDraftsResponse": "google.ads.googleads.v15.services.types.campaign_draft_service", + "MutateCampaignExtensionSettingResult": "google.ads.googleads.v15.services.types.campaign_extension_setting_service", + "MutateCampaignExtensionSettingsRequest": "google.ads.googleads.v15.services.types.campaign_extension_setting_service", + "MutateCampaignExtensionSettingsResponse": "google.ads.googleads.v15.services.types.campaign_extension_setting_service", + "MutateCampaignFeedResult": "google.ads.googleads.v15.services.types.campaign_feed_service", + "MutateCampaignFeedsRequest": "google.ads.googleads.v15.services.types.campaign_feed_service", + "MutateCampaignFeedsResponse": "google.ads.googleads.v15.services.types.campaign_feed_service", + "MutateCampaignGroupResult": "google.ads.googleads.v15.services.types.campaign_group_service", + "MutateCampaignGroupsRequest": "google.ads.googleads.v15.services.types.campaign_group_service", + "MutateCampaignGroupsResponse": "google.ads.googleads.v15.services.types.campaign_group_service", + "MutateCampaignLabelResult": "google.ads.googleads.v15.services.types.campaign_label_service", + "MutateCampaignLabelsRequest": "google.ads.googleads.v15.services.types.campaign_label_service", + "MutateCampaignLabelsResponse": "google.ads.googleads.v15.services.types.campaign_label_service", + "MutateCampaignResult": "google.ads.googleads.v15.services.types.campaign_service", + "MutateCampaignSharedSetResult": "google.ads.googleads.v15.services.types.campaign_shared_set_service", + "MutateCampaignSharedSetsRequest": "google.ads.googleads.v15.services.types.campaign_shared_set_service", + "MutateCampaignSharedSetsResponse": "google.ads.googleads.v15.services.types.campaign_shared_set_service", + "MutateCampaignsRequest": "google.ads.googleads.v15.services.types.campaign_service", + "MutateCampaignsResponse": "google.ads.googleads.v15.services.types.campaign_service", + "MutateConversionActionResult": "google.ads.googleads.v15.services.types.conversion_action_service", + "MutateConversionActionsRequest": "google.ads.googleads.v15.services.types.conversion_action_service", + "MutateConversionActionsResponse": "google.ads.googleads.v15.services.types.conversion_action_service", + "MutateConversionCustomVariableResult": "google.ads.googleads.v15.services.types.conversion_custom_variable_service", + "MutateConversionCustomVariablesRequest": "google.ads.googleads.v15.services.types.conversion_custom_variable_service", + "MutateConversionCustomVariablesResponse": "google.ads.googleads.v15.services.types.conversion_custom_variable_service", + "MutateConversionGoalCampaignConfigResult": "google.ads.googleads.v15.services.types.conversion_goal_campaign_config_service", + "MutateConversionGoalCampaignConfigsRequest": "google.ads.googleads.v15.services.types.conversion_goal_campaign_config_service", + "MutateConversionGoalCampaignConfigsResponse": "google.ads.googleads.v15.services.types.conversion_goal_campaign_config_service", + "MutateConversionValueRuleResult": "google.ads.googleads.v15.services.types.conversion_value_rule_service", + "MutateConversionValueRuleSetResult": "google.ads.googleads.v15.services.types.conversion_value_rule_set_service", + "MutateConversionValueRuleSetsRequest": "google.ads.googleads.v15.services.types.conversion_value_rule_set_service", + "MutateConversionValueRuleSetsResponse": "google.ads.googleads.v15.services.types.conversion_value_rule_set_service", + "MutateConversionValueRulesRequest": "google.ads.googleads.v15.services.types.conversion_value_rule_service", + "MutateConversionValueRulesResponse": "google.ads.googleads.v15.services.types.conversion_value_rule_service", + "MutateCustomAudienceResult": "google.ads.googleads.v15.services.types.custom_audience_service", + "MutateCustomAudiencesRequest": "google.ads.googleads.v15.services.types.custom_audience_service", + "MutateCustomAudiencesResponse": "google.ads.googleads.v15.services.types.custom_audience_service", + "MutateCustomConversionGoalResult": "google.ads.googleads.v15.services.types.custom_conversion_goal_service", + "MutateCustomConversionGoalsRequest": "google.ads.googleads.v15.services.types.custom_conversion_goal_service", + "MutateCustomConversionGoalsResponse": "google.ads.googleads.v15.services.types.custom_conversion_goal_service", + "MutateCustomerAssetResult": "google.ads.googleads.v15.services.types.customer_asset_service", + "MutateCustomerAssetSetResult": "google.ads.googleads.v15.services.types.customer_asset_set_service", + "MutateCustomerAssetSetsRequest": "google.ads.googleads.v15.services.types.customer_asset_set_service", + "MutateCustomerAssetSetsResponse": "google.ads.googleads.v15.services.types.customer_asset_set_service", + "MutateCustomerAssetsRequest": "google.ads.googleads.v15.services.types.customer_asset_service", + "MutateCustomerAssetsResponse": "google.ads.googleads.v15.services.types.customer_asset_service", + "MutateCustomerClientLinkRequest": "google.ads.googleads.v15.services.types.customer_client_link_service", + "MutateCustomerClientLinkResponse": "google.ads.googleads.v15.services.types.customer_client_link_service", + "MutateCustomerClientLinkResult": "google.ads.googleads.v15.services.types.customer_client_link_service", + "MutateCustomerConversionGoalResult": "google.ads.googleads.v15.services.types.customer_conversion_goal_service", + "MutateCustomerConversionGoalsRequest": "google.ads.googleads.v15.services.types.customer_conversion_goal_service", + "MutateCustomerConversionGoalsResponse": "google.ads.googleads.v15.services.types.customer_conversion_goal_service", + "MutateCustomerCustomizerResult": "google.ads.googleads.v15.services.types.customer_customizer_service", + "MutateCustomerCustomizersRequest": "google.ads.googleads.v15.services.types.customer_customizer_service", + "MutateCustomerCustomizersResponse": "google.ads.googleads.v15.services.types.customer_customizer_service", + "MutateCustomerExtensionSettingResult": "google.ads.googleads.v15.services.types.customer_extension_setting_service", + "MutateCustomerExtensionSettingsRequest": "google.ads.googleads.v15.services.types.customer_extension_setting_service", + "MutateCustomerExtensionSettingsResponse": "google.ads.googleads.v15.services.types.customer_extension_setting_service", + "MutateCustomerFeedResult": "google.ads.googleads.v15.services.types.customer_feed_service", + "MutateCustomerFeedsRequest": "google.ads.googleads.v15.services.types.customer_feed_service", + "MutateCustomerFeedsResponse": "google.ads.googleads.v15.services.types.customer_feed_service", + "MutateCustomerLabelResult": "google.ads.googleads.v15.services.types.customer_label_service", + "MutateCustomerLabelsRequest": "google.ads.googleads.v15.services.types.customer_label_service", + "MutateCustomerLabelsResponse": "google.ads.googleads.v15.services.types.customer_label_service", + "MutateCustomerManagerLinkRequest": "google.ads.googleads.v15.services.types.customer_manager_link_service", + "MutateCustomerManagerLinkResponse": "google.ads.googleads.v15.services.types.customer_manager_link_service", + "MutateCustomerManagerLinkResult": "google.ads.googleads.v15.services.types.customer_manager_link_service", + "MutateCustomerNegativeCriteriaRequest": "google.ads.googleads.v15.services.types.customer_negative_criterion_service", + "MutateCustomerNegativeCriteriaResponse": "google.ads.googleads.v15.services.types.customer_negative_criterion_service", + "MutateCustomerNegativeCriteriaResult": "google.ads.googleads.v15.services.types.customer_negative_criterion_service", + "MutateCustomerRequest": "google.ads.googleads.v15.services.types.customer_service", + "MutateCustomerResponse": "google.ads.googleads.v15.services.types.customer_service", + "MutateCustomerResult": "google.ads.googleads.v15.services.types.customer_service", + "MutateCustomerSkAdNetworkConversionValueSchemaRequest": "google.ads.googleads.v15.services.types.customer_sk_ad_network_conversion_value_schema_service", + "MutateCustomerSkAdNetworkConversionValueSchemaResponse": "google.ads.googleads.v15.services.types.customer_sk_ad_network_conversion_value_schema_service", + "MutateCustomerSkAdNetworkConversionValueSchemaResult": "google.ads.googleads.v15.services.types.customer_sk_ad_network_conversion_value_schema_service", + "MutateCustomerUserAccessInvitationRequest": "google.ads.googleads.v15.services.types.customer_user_access_invitation_service", + "MutateCustomerUserAccessInvitationResponse": "google.ads.googleads.v15.services.types.customer_user_access_invitation_service", + "MutateCustomerUserAccessInvitationResult": "google.ads.googleads.v15.services.types.customer_user_access_invitation_service", + "MutateCustomerUserAccessRequest": "google.ads.googleads.v15.services.types.customer_user_access_service", + "MutateCustomerUserAccessResponse": "google.ads.googleads.v15.services.types.customer_user_access_service", + "MutateCustomerUserAccessResult": "google.ads.googleads.v15.services.types.customer_user_access_service", + "MutateCustomInterestResult": "google.ads.googleads.v15.services.types.custom_interest_service", + "MutateCustomInterestsRequest": "google.ads.googleads.v15.services.types.custom_interest_service", + "MutateCustomInterestsResponse": "google.ads.googleads.v15.services.types.custom_interest_service", + "MutateCustomizerAttributeResult": "google.ads.googleads.v15.services.types.customizer_attribute_service", + "MutateCustomizerAttributesRequest": "google.ads.googleads.v15.services.types.customizer_attribute_service", + "MutateCustomizerAttributesResponse": "google.ads.googleads.v15.services.types.customizer_attribute_service", + "MutateExperimentArmResult": "google.ads.googleads.v15.services.types.experiment_arm_service", + "MutateExperimentArmsRequest": "google.ads.googleads.v15.services.types.experiment_arm_service", + "MutateExperimentArmsResponse": "google.ads.googleads.v15.services.types.experiment_arm_service", + "MutateExperimentResult": "google.ads.googleads.v15.services.types.experiment_service", + "MutateExperimentsRequest": "google.ads.googleads.v15.services.types.experiment_service", + "MutateExperimentsResponse": "google.ads.googleads.v15.services.types.experiment_service", + "MutateExtensionFeedItemResult": "google.ads.googleads.v15.services.types.extension_feed_item_service", + "MutateExtensionFeedItemsRequest": "google.ads.googleads.v15.services.types.extension_feed_item_service", + "MutateExtensionFeedItemsResponse": "google.ads.googleads.v15.services.types.extension_feed_item_service", + "MutateFeedItemResult": "google.ads.googleads.v15.services.types.feed_item_service", + "MutateFeedItemSetLinkResult": "google.ads.googleads.v15.services.types.feed_item_set_link_service", + "MutateFeedItemSetLinksRequest": "google.ads.googleads.v15.services.types.feed_item_set_link_service", + "MutateFeedItemSetLinksResponse": "google.ads.googleads.v15.services.types.feed_item_set_link_service", + "MutateFeedItemSetResult": "google.ads.googleads.v15.services.types.feed_item_set_service", + "MutateFeedItemSetsRequest": "google.ads.googleads.v15.services.types.feed_item_set_service", + "MutateFeedItemSetsResponse": "google.ads.googleads.v15.services.types.feed_item_set_service", + "MutateFeedItemsRequest": "google.ads.googleads.v15.services.types.feed_item_service", + "MutateFeedItemsResponse": "google.ads.googleads.v15.services.types.feed_item_service", + "MutateFeedItemTargetResult": "google.ads.googleads.v15.services.types.feed_item_target_service", + "MutateFeedItemTargetsRequest": "google.ads.googleads.v15.services.types.feed_item_target_service", + "MutateFeedItemTargetsResponse": "google.ads.googleads.v15.services.types.feed_item_target_service", + "MutateFeedMappingResult": "google.ads.googleads.v15.services.types.feed_mapping_service", + "MutateFeedMappingsRequest": "google.ads.googleads.v15.services.types.feed_mapping_service", + "MutateFeedMappingsResponse": "google.ads.googleads.v15.services.types.feed_mapping_service", + "MutateFeedResult": "google.ads.googleads.v15.services.types.feed_service", + "MutateFeedsRequest": "google.ads.googleads.v15.services.types.feed_service", + "MutateFeedsResponse": "google.ads.googleads.v15.services.types.feed_service", + "MutateGoogleAdsRequest": "google.ads.googleads.v15.services.types.google_ads_service", + "MutateGoogleAdsResponse": "google.ads.googleads.v15.services.types.google_ads_service", + "MutateKeywordPlanAdGroupKeywordResult": "google.ads.googleads.v15.services.types.keyword_plan_ad_group_keyword_service", + "MutateKeywordPlanAdGroupKeywordsRequest": "google.ads.googleads.v15.services.types.keyword_plan_ad_group_keyword_service", + "MutateKeywordPlanAdGroupKeywordsResponse": "google.ads.googleads.v15.services.types.keyword_plan_ad_group_keyword_service", + "MutateKeywordPlanAdGroupResult": "google.ads.googleads.v15.services.types.keyword_plan_ad_group_service", + "MutateKeywordPlanAdGroupsRequest": "google.ads.googleads.v15.services.types.keyword_plan_ad_group_service", + "MutateKeywordPlanAdGroupsResponse": "google.ads.googleads.v15.services.types.keyword_plan_ad_group_service", + "MutateKeywordPlanCampaignKeywordResult": "google.ads.googleads.v15.services.types.keyword_plan_campaign_keyword_service", + "MutateKeywordPlanCampaignKeywordsRequest": "google.ads.googleads.v15.services.types.keyword_plan_campaign_keyword_service", + "MutateKeywordPlanCampaignKeywordsResponse": "google.ads.googleads.v15.services.types.keyword_plan_campaign_keyword_service", + "MutateKeywordPlanCampaignResult": "google.ads.googleads.v15.services.types.keyword_plan_campaign_service", + "MutateKeywordPlanCampaignsRequest": "google.ads.googleads.v15.services.types.keyword_plan_campaign_service", + "MutateKeywordPlanCampaignsResponse": "google.ads.googleads.v15.services.types.keyword_plan_campaign_service", + "MutateKeywordPlansRequest": "google.ads.googleads.v15.services.types.keyword_plan_service", + "MutateKeywordPlansResponse": "google.ads.googleads.v15.services.types.keyword_plan_service", + "MutateKeywordPlansResult": "google.ads.googleads.v15.services.types.keyword_plan_service", + "MutateLabelResult": "google.ads.googleads.v15.services.types.label_service", + "MutateLabelsRequest": "google.ads.googleads.v15.services.types.label_service", + "MutateLabelsResponse": "google.ads.googleads.v15.services.types.label_service", + "MutateOperation": "google.ads.googleads.v15.services.types.google_ads_service", + "MutateOperationResponse": "google.ads.googleads.v15.services.types.google_ads_service", + "MutateRecommendationSubscriptionRequest": "google.ads.googleads.v15.services.types.recommendation_subscription_service", + "MutateRecommendationSubscriptionResponse": "google.ads.googleads.v15.services.types.recommendation_subscription_service", + "MutateRecommendationSubscriptionResult": "google.ads.googleads.v15.services.types.recommendation_subscription_service", + "MutateRemarketingActionResult": "google.ads.googleads.v15.services.types.remarketing_action_service", + "MutateRemarketingActionsRequest": "google.ads.googleads.v15.services.types.remarketing_action_service", + "MutateRemarketingActionsResponse": "google.ads.googleads.v15.services.types.remarketing_action_service", + "MutateSharedCriteriaRequest": "google.ads.googleads.v15.services.types.shared_criterion_service", + "MutateSharedCriteriaResponse": "google.ads.googleads.v15.services.types.shared_criterion_service", + "MutateSharedCriterionResult": "google.ads.googleads.v15.services.types.shared_criterion_service", + "MutateSharedSetResult": "google.ads.googleads.v15.services.types.shared_set_service", + "MutateSharedSetsRequest": "google.ads.googleads.v15.services.types.shared_set_service", + "MutateSharedSetsResponse": "google.ads.googleads.v15.services.types.shared_set_service", + "MutateSmartCampaignSettingResult": "google.ads.googleads.v15.services.types.smart_campaign_setting_service", + "MutateSmartCampaignSettingsRequest": "google.ads.googleads.v15.services.types.smart_campaign_setting_service", + "MutateSmartCampaignSettingsResponse": "google.ads.googleads.v15.services.types.smart_campaign_setting_service", + "MutateUserListResult": "google.ads.googleads.v15.services.types.user_list_service", + "MutateUserListsRequest": "google.ads.googleads.v15.services.types.user_list_service", + "MutateUserListsResponse": "google.ads.googleads.v15.services.types.user_list_service", + "OfflineUserDataJobOperation": "google.ads.googleads.v15.services.types.offline_user_data_job_service", + "OnTargetAudienceMetrics": "google.ads.googleads.v15.services.types.reach_plan_service", + "PlannableLocation": "google.ads.googleads.v15.services.types.reach_plan_service", + "PlannableTargeting": "google.ads.googleads.v15.services.types.reach_plan_service", + "PlannedProduct": "google.ads.googleads.v15.services.types.reach_plan_service", + "PlannedProductForecast": "google.ads.googleads.v15.services.types.reach_plan_service", + "PlannedProductReachForecast": "google.ads.googleads.v15.services.types.reach_plan_service", + "ProductMetadata": "google.ads.googleads.v15.services.types.reach_plan_service", + "PromoteCampaignDraftRequest": "google.ads.googleads.v15.services.types.campaign_draft_service", + "PromoteExperimentMetadata": "google.ads.googleads.v15.services.types.experiment_service", + "PromoteExperimentRequest": "google.ads.googleads.v15.services.types.experiment_service", + "ReachCurve": "google.ads.googleads.v15.services.types.reach_plan_service", + "ReachForecast": "google.ads.googleads.v15.services.types.reach_plan_service", + "RecommendationSubscriptionOperation": "google.ads.googleads.v15.services.types.recommendation_subscription_service", + "RegenerateShareableLinkIdRequest": "google.ads.googleads.v15.services.types.third_party_app_analytics_link_service", + "RegenerateShareableLinkIdResponse": "google.ads.googleads.v15.services.types.third_party_app_analytics_link_service", + "RemarketingActionOperation": "google.ads.googleads.v15.services.types.remarketing_action_service", + "RemoveProductLinkRequest": "google.ads.googleads.v15.services.types.product_link_service", + "RemoveProductLinkResponse": "google.ads.googleads.v15.services.types.product_link_service", + "RestatementValue": "google.ads.googleads.v15.services.types.conversion_adjustment_upload_service", + "RunBatchJobRequest": "google.ads.googleads.v15.services.types.batch_job_service", + "RunOfflineUserDataJobRequest": "google.ads.googleads.v15.services.types.offline_user_data_job_service", + "ScheduleExperimentMetadata": "google.ads.googleads.v15.services.types.experiment_service", + "ScheduleExperimentRequest": "google.ads.googleads.v15.services.types.experiment_service", + "SearchGoogleAdsFieldsRequest": "google.ads.googleads.v15.services.types.google_ads_field_service", + "SearchGoogleAdsFieldsResponse": "google.ads.googleads.v15.services.types.google_ads_field_service", + "SearchGoogleAdsRequest": "google.ads.googleads.v15.services.types.google_ads_service", + "SearchGoogleAdsResponse": "google.ads.googleads.v15.services.types.google_ads_service", + "SearchGoogleAdsStreamRequest": "google.ads.googleads.v15.services.types.google_ads_service", + "SearchGoogleAdsStreamResponse": "google.ads.googleads.v15.services.types.google_ads_service", + "SharedCriterionOperation": "google.ads.googleads.v15.services.types.shared_criterion_service", + "SharedSetOperation": "google.ads.googleads.v15.services.types.shared_set_service", + "SiteSeed": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "SmartCampaignEligibleDetails": "google.ads.googleads.v15.services.types.smart_campaign_setting_service", + "SmartCampaignEndedDetails": "google.ads.googleads.v15.services.types.smart_campaign_setting_service", + "SmartCampaignNotEligibleDetails": "google.ads.googleads.v15.services.types.smart_campaign_setting_service", + "SmartCampaignPausedDetails": "google.ads.googleads.v15.services.types.smart_campaign_setting_service", + "SmartCampaignRemovedDetails": "google.ads.googleads.v15.services.types.smart_campaign_setting_service", + "SmartCampaignSettingOperation": "google.ads.googleads.v15.services.types.smart_campaign_setting_service", + "SmartCampaignSuggestionInfo": "google.ads.googleads.v15.services.types.smart_campaign_suggest_service", + "SuggestBrandsRequest": "google.ads.googleads.v15.services.types.brand_suggestion_service", + "SuggestBrandsResponse": "google.ads.googleads.v15.services.types.brand_suggestion_service", + "SuggestGeoTargetConstantsRequest": "google.ads.googleads.v15.services.types.geo_target_constant_service", + "SuggestGeoTargetConstantsResponse": "google.ads.googleads.v15.services.types.geo_target_constant_service", + "SuggestKeywordThemeConstantsRequest": "google.ads.googleads.v15.services.types.keyword_theme_constant_service", + "SuggestKeywordThemeConstantsResponse": "google.ads.googleads.v15.services.types.keyword_theme_constant_service", + "SuggestKeywordThemesRequest": "google.ads.googleads.v15.services.types.smart_campaign_suggest_service", + "SuggestKeywordThemesResponse": "google.ads.googleads.v15.services.types.smart_campaign_suggest_service", + "SuggestSmartCampaignAdRequest": "google.ads.googleads.v15.services.types.smart_campaign_suggest_service", + "SuggestSmartCampaignAdResponse": "google.ads.googleads.v15.services.types.smart_campaign_suggest_service", + "SuggestSmartCampaignBudgetOptionsRequest": "google.ads.googleads.v15.services.types.smart_campaign_suggest_service", + "SuggestSmartCampaignBudgetOptionsResponse": "google.ads.googleads.v15.services.types.smart_campaign_suggest_service", + "SuggestTravelAssetsRequest": "google.ads.googleads.v15.services.types.travel_asset_suggestion_service", + "SuggestTravelAssetsResponse": "google.ads.googleads.v15.services.types.travel_asset_suggestion_service", + "SurfaceTargeting": "google.ads.googleads.v15.services.types.reach_plan_service", + "SurfaceTargetingCombinations": "google.ads.googleads.v15.services.types.reach_plan_service", + "TargetFrequencySettings": "google.ads.googleads.v15.services.types.reach_plan_service", + "Targeting": "google.ads.googleads.v15.services.types.reach_plan_service", + "TargetingSuggestionMetrics": "google.ads.googleads.v15.services.types.audience_insights_service", + "UnusableAdGroup": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "UpdateProductLinkInvitationRequest": "google.ads.googleads.v15.services.types.product_link_invitation_service", + "UpdateProductLinkInvitationResponse": "google.ads.googleads.v15.services.types.product_link_invitation_service", + "UploadCallConversionsRequest": "google.ads.googleads.v15.services.types.conversion_upload_service", + "UploadCallConversionsResponse": "google.ads.googleads.v15.services.types.conversion_upload_service", + "UploadClickConversionsRequest": "google.ads.googleads.v15.services.types.conversion_upload_service", + "UploadClickConversionsResponse": "google.ads.googleads.v15.services.types.conversion_upload_service", + "UploadConversionAdjustmentsRequest": "google.ads.googleads.v15.services.types.conversion_adjustment_upload_service", + "UploadConversionAdjustmentsResponse": "google.ads.googleads.v15.services.types.conversion_adjustment_upload_service", + "UploadUserDataRequest": "google.ads.googleads.v15.services.types.user_data_service", + "UploadUserDataResponse": "google.ads.googleads.v15.services.types.user_data_service", + "UrlSeed": "google.ads.googleads.v15.services.types.keyword_plan_idea_service", + "UserDataOperation": "google.ads.googleads.v15.services.types.user_data_service", + "UserListOperation": "google.ads.googleads.v15.services.types.user_list_service", + "YouTubeChannelAttributeMetadata": "google.ads.googleads.v15.services.types.audience_insights_service", + "YouTubeSelectLineUp": "google.ads.googleads.v15.services.types.reach_plan_service", + "YouTubeSelectSettings": "google.ads.googleads.v15.services.types.reach_plan_service", + # Enum types + # Client classes and transports + "AccountBudgetProposalServiceClient": "google.ads.googleads.v15.services.services.account_budget_proposal_service", + "AccountBudgetProposalServiceTransport": "google.ads.googleads.v15.services.services.account_budget_proposal_service.transports", + "AccountBudgetProposalServiceGrpcTransport": "google.ads.googleads.v15.services.services.account_budget_proposal_service.transports", + "AccountLinkServiceClient": "google.ads.googleads.v15.services.services.account_link_service", + "AccountLinkServiceTransport": "google.ads.googleads.v15.services.services.account_link_service.transports", + "AccountLinkServiceGrpcTransport": "google.ads.googleads.v15.services.services.account_link_service.transports", + "AdGroupAdLabelServiceClient": "google.ads.googleads.v15.services.services.ad_group_ad_label_service", + "AdGroupAdLabelServiceTransport": "google.ads.googleads.v15.services.services.ad_group_ad_label_service.transports", + "AdGroupAdLabelServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_group_ad_label_service.transports", + "AdGroupAdServiceClient": "google.ads.googleads.v15.services.services.ad_group_ad_service", + "AdGroupAdServiceTransport": "google.ads.googleads.v15.services.services.ad_group_ad_service.transports", + "AdGroupAdServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_group_ad_service.transports", + "AdGroupAssetServiceClient": "google.ads.googleads.v15.services.services.ad_group_asset_service", + "AdGroupAssetServiceTransport": "google.ads.googleads.v15.services.services.ad_group_asset_service.transports", + "AdGroupAssetServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_group_asset_service.transports", + "AdGroupAssetSetServiceClient": "google.ads.googleads.v15.services.services.ad_group_asset_set_service", + "AdGroupAssetSetServiceTransport": "google.ads.googleads.v15.services.services.ad_group_asset_set_service.transports", + "AdGroupAssetSetServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_group_asset_set_service.transports", + "AdGroupBidModifierServiceClient": "google.ads.googleads.v15.services.services.ad_group_bid_modifier_service", + "AdGroupBidModifierServiceTransport": "google.ads.googleads.v15.services.services.ad_group_bid_modifier_service.transports", + "AdGroupBidModifierServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_group_bid_modifier_service.transports", + "AdGroupCriterionCustomizerServiceClient": "google.ads.googleads.v15.services.services.ad_group_criterion_customizer_service", + "AdGroupCriterionCustomizerServiceTransport": "google.ads.googleads.v15.services.services.ad_group_criterion_customizer_service.transports", + "AdGroupCriterionCustomizerServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_group_criterion_customizer_service.transports", + "AdGroupCriterionLabelServiceClient": "google.ads.googleads.v15.services.services.ad_group_criterion_label_service", + "AdGroupCriterionLabelServiceTransport": "google.ads.googleads.v15.services.services.ad_group_criterion_label_service.transports", + "AdGroupCriterionLabelServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_group_criterion_label_service.transports", + "AdGroupCriterionServiceClient": "google.ads.googleads.v15.services.services.ad_group_criterion_service", + "AdGroupCriterionServiceTransport": "google.ads.googleads.v15.services.services.ad_group_criterion_service.transports", + "AdGroupCriterionServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_group_criterion_service.transports", + "AdGroupCustomizerServiceClient": "google.ads.googleads.v15.services.services.ad_group_customizer_service", + "AdGroupCustomizerServiceTransport": "google.ads.googleads.v15.services.services.ad_group_customizer_service.transports", + "AdGroupCustomizerServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_group_customizer_service.transports", + "AdGroupExtensionSettingServiceClient": "google.ads.googleads.v15.services.services.ad_group_extension_setting_service", + "AdGroupExtensionSettingServiceTransport": "google.ads.googleads.v15.services.services.ad_group_extension_setting_service.transports", + "AdGroupExtensionSettingServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_group_extension_setting_service.transports", + "AdGroupFeedServiceClient": "google.ads.googleads.v15.services.services.ad_group_feed_service", + "AdGroupFeedServiceTransport": "google.ads.googleads.v15.services.services.ad_group_feed_service.transports", + "AdGroupFeedServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_group_feed_service.transports", + "AdGroupLabelServiceClient": "google.ads.googleads.v15.services.services.ad_group_label_service", + "AdGroupLabelServiceTransport": "google.ads.googleads.v15.services.services.ad_group_label_service.transports", + "AdGroupLabelServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_group_label_service.transports", + "AdGroupServiceClient": "google.ads.googleads.v15.services.services.ad_group_service", + "AdGroupServiceTransport": "google.ads.googleads.v15.services.services.ad_group_service.transports", + "AdGroupServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_group_service.transports", + "AdParameterServiceClient": "google.ads.googleads.v15.services.services.ad_parameter_service", + "AdParameterServiceTransport": "google.ads.googleads.v15.services.services.ad_parameter_service.transports", + "AdParameterServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_parameter_service.transports", + "AdServiceClient": "google.ads.googleads.v15.services.services.ad_service", + "AdServiceTransport": "google.ads.googleads.v15.services.services.ad_service.transports", + "AdServiceGrpcTransport": "google.ads.googleads.v15.services.services.ad_service.transports", + "AssetGroupAssetServiceClient": "google.ads.googleads.v15.services.services.asset_group_asset_service", + "AssetGroupAssetServiceTransport": "google.ads.googleads.v15.services.services.asset_group_asset_service.transports", + "AssetGroupAssetServiceGrpcTransport": "google.ads.googleads.v15.services.services.asset_group_asset_service.transports", + "AssetGroupListingGroupFilterServiceClient": "google.ads.googleads.v15.services.services.asset_group_listing_group_filter_service", + "AssetGroupListingGroupFilterServiceTransport": "google.ads.googleads.v15.services.services.asset_group_listing_group_filter_service.transports", + "AssetGroupListingGroupFilterServiceGrpcTransport": "google.ads.googleads.v15.services.services.asset_group_listing_group_filter_service.transports", + "AssetGroupServiceClient": "google.ads.googleads.v15.services.services.asset_group_service", + "AssetGroupServiceTransport": "google.ads.googleads.v15.services.services.asset_group_service.transports", + "AssetGroupServiceGrpcTransport": "google.ads.googleads.v15.services.services.asset_group_service.transports", + "AssetGroupSignalServiceClient": "google.ads.googleads.v15.services.services.asset_group_signal_service", + "AssetGroupSignalServiceTransport": "google.ads.googleads.v15.services.services.asset_group_signal_service.transports", + "AssetGroupSignalServiceGrpcTransport": "google.ads.googleads.v15.services.services.asset_group_signal_service.transports", + "AssetServiceClient": "google.ads.googleads.v15.services.services.asset_service", + "AssetServiceTransport": "google.ads.googleads.v15.services.services.asset_service.transports", + "AssetServiceGrpcTransport": "google.ads.googleads.v15.services.services.asset_service.transports", + "AssetSetAssetServiceClient": "google.ads.googleads.v15.services.services.asset_set_asset_service", + "AssetSetAssetServiceTransport": "google.ads.googleads.v15.services.services.asset_set_asset_service.transports", + "AssetSetAssetServiceGrpcTransport": "google.ads.googleads.v15.services.services.asset_set_asset_service.transports", + "AssetSetServiceClient": "google.ads.googleads.v15.services.services.asset_set_service", + "AssetSetServiceTransport": "google.ads.googleads.v15.services.services.asset_set_service.transports", + "AssetSetServiceGrpcTransport": "google.ads.googleads.v15.services.services.asset_set_service.transports", + "AudienceInsightsServiceClient": "google.ads.googleads.v15.services.services.audience_insights_service", + "AudienceInsightsServiceTransport": "google.ads.googleads.v15.services.services.audience_insights_service.transports", + "AudienceInsightsServiceGrpcTransport": "google.ads.googleads.v15.services.services.audience_insights_service.transports", + "AudienceServiceClient": "google.ads.googleads.v15.services.services.audience_service", + "AudienceServiceTransport": "google.ads.googleads.v15.services.services.audience_service.transports", + "AudienceServiceGrpcTransport": "google.ads.googleads.v15.services.services.audience_service.transports", + "BatchJobServiceClient": "google.ads.googleads.v15.services.services.batch_job_service", + "BatchJobServiceTransport": "google.ads.googleads.v15.services.services.batch_job_service.transports", + "BatchJobServiceGrpcTransport": "google.ads.googleads.v15.services.services.batch_job_service.transports", + "BiddingDataExclusionServiceClient": "google.ads.googleads.v15.services.services.bidding_data_exclusion_service", + "BiddingDataExclusionServiceTransport": "google.ads.googleads.v15.services.services.bidding_data_exclusion_service.transports", + "BiddingDataExclusionServiceGrpcTransport": "google.ads.googleads.v15.services.services.bidding_data_exclusion_service.transports", + "BiddingSeasonalityAdjustmentServiceClient": "google.ads.googleads.v15.services.services.bidding_seasonality_adjustment_service", + "BiddingSeasonalityAdjustmentServiceTransport": "google.ads.googleads.v15.services.services.bidding_seasonality_adjustment_service.transports", + "BiddingSeasonalityAdjustmentServiceGrpcTransport": "google.ads.googleads.v15.services.services.bidding_seasonality_adjustment_service.transports", + "BiddingStrategyServiceClient": "google.ads.googleads.v15.services.services.bidding_strategy_service", + "BiddingStrategyServiceTransport": "google.ads.googleads.v15.services.services.bidding_strategy_service.transports", + "BiddingStrategyServiceGrpcTransport": "google.ads.googleads.v15.services.services.bidding_strategy_service.transports", + "BillingSetupServiceClient": "google.ads.googleads.v15.services.services.billing_setup_service", + "BillingSetupServiceTransport": "google.ads.googleads.v15.services.services.billing_setup_service.transports", + "BillingSetupServiceGrpcTransport": "google.ads.googleads.v15.services.services.billing_setup_service.transports", + "BrandSuggestionServiceClient": "google.ads.googleads.v15.services.services.brand_suggestion_service", + "BrandSuggestionServiceTransport": "google.ads.googleads.v15.services.services.brand_suggestion_service.transports", + "BrandSuggestionServiceGrpcTransport": "google.ads.googleads.v15.services.services.brand_suggestion_service.transports", + "CampaignAssetServiceClient": "google.ads.googleads.v15.services.services.campaign_asset_service", + "CampaignAssetServiceTransport": "google.ads.googleads.v15.services.services.campaign_asset_service.transports", + "CampaignAssetServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_asset_service.transports", + "CampaignAssetSetServiceClient": "google.ads.googleads.v15.services.services.campaign_asset_set_service", + "CampaignAssetSetServiceTransport": "google.ads.googleads.v15.services.services.campaign_asset_set_service.transports", + "CampaignAssetSetServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_asset_set_service.transports", + "CampaignBidModifierServiceClient": "google.ads.googleads.v15.services.services.campaign_bid_modifier_service", + "CampaignBidModifierServiceTransport": "google.ads.googleads.v15.services.services.campaign_bid_modifier_service.transports", + "CampaignBidModifierServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_bid_modifier_service.transports", + "CampaignBudgetServiceClient": "google.ads.googleads.v15.services.services.campaign_budget_service", + "CampaignBudgetServiceTransport": "google.ads.googleads.v15.services.services.campaign_budget_service.transports", + "CampaignBudgetServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_budget_service.transports", + "CampaignConversionGoalServiceClient": "google.ads.googleads.v15.services.services.campaign_conversion_goal_service", + "CampaignConversionGoalServiceTransport": "google.ads.googleads.v15.services.services.campaign_conversion_goal_service.transports", + "CampaignConversionGoalServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_conversion_goal_service.transports", + "CampaignCriterionServiceClient": "google.ads.googleads.v15.services.services.campaign_criterion_service", + "CampaignCriterionServiceTransport": "google.ads.googleads.v15.services.services.campaign_criterion_service.transports", + "CampaignCriterionServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_criterion_service.transports", + "CampaignCustomizerServiceClient": "google.ads.googleads.v15.services.services.campaign_customizer_service", + "CampaignCustomizerServiceTransport": "google.ads.googleads.v15.services.services.campaign_customizer_service.transports", + "CampaignCustomizerServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_customizer_service.transports", + "CampaignDraftServiceClient": "google.ads.googleads.v15.services.services.campaign_draft_service", + "CampaignDraftServiceTransport": "google.ads.googleads.v15.services.services.campaign_draft_service.transports", + "CampaignDraftServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_draft_service.transports", + "CampaignExtensionSettingServiceClient": "google.ads.googleads.v15.services.services.campaign_extension_setting_service", + "CampaignExtensionSettingServiceTransport": "google.ads.googleads.v15.services.services.campaign_extension_setting_service.transports", + "CampaignExtensionSettingServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_extension_setting_service.transports", + "CampaignFeedServiceClient": "google.ads.googleads.v15.services.services.campaign_feed_service", + "CampaignFeedServiceTransport": "google.ads.googleads.v15.services.services.campaign_feed_service.transports", + "CampaignFeedServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_feed_service.transports", + "CampaignGroupServiceClient": "google.ads.googleads.v15.services.services.campaign_group_service", + "CampaignGroupServiceTransport": "google.ads.googleads.v15.services.services.campaign_group_service.transports", + "CampaignGroupServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_group_service.transports", + "CampaignLabelServiceClient": "google.ads.googleads.v15.services.services.campaign_label_service", + "CampaignLabelServiceTransport": "google.ads.googleads.v15.services.services.campaign_label_service.transports", + "CampaignLabelServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_label_service.transports", + "CampaignLifecycleGoalServiceClient": "google.ads.googleads.v15.services.services.campaign_lifecycle_goal_service", + "CampaignLifecycleGoalServiceTransport": "google.ads.googleads.v15.services.services.campaign_lifecycle_goal_service.transports", + "CampaignLifecycleGoalServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_lifecycle_goal_service.transports", + "CampaignServiceClient": "google.ads.googleads.v15.services.services.campaign_service", + "CampaignServiceTransport": "google.ads.googleads.v15.services.services.campaign_service.transports", + "CampaignServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_service.transports", + "CampaignSharedSetServiceClient": "google.ads.googleads.v15.services.services.campaign_shared_set_service", + "CampaignSharedSetServiceTransport": "google.ads.googleads.v15.services.services.campaign_shared_set_service.transports", + "CampaignSharedSetServiceGrpcTransport": "google.ads.googleads.v15.services.services.campaign_shared_set_service.transports", + "ConversionActionServiceClient": "google.ads.googleads.v15.services.services.conversion_action_service", + "ConversionActionServiceTransport": "google.ads.googleads.v15.services.services.conversion_action_service.transports", + "ConversionActionServiceGrpcTransport": "google.ads.googleads.v15.services.services.conversion_action_service.transports", + "ConversionAdjustmentUploadServiceClient": "google.ads.googleads.v15.services.services.conversion_adjustment_upload_service", + "ConversionAdjustmentUploadServiceTransport": "google.ads.googleads.v15.services.services.conversion_adjustment_upload_service.transports", + "ConversionAdjustmentUploadServiceGrpcTransport": "google.ads.googleads.v15.services.services.conversion_adjustment_upload_service.transports", + "ConversionCustomVariableServiceClient": "google.ads.googleads.v15.services.services.conversion_custom_variable_service", + "ConversionCustomVariableServiceTransport": "google.ads.googleads.v15.services.services.conversion_custom_variable_service.transports", + "ConversionCustomVariableServiceGrpcTransport": "google.ads.googleads.v15.services.services.conversion_custom_variable_service.transports", + "ConversionGoalCampaignConfigServiceClient": "google.ads.googleads.v15.services.services.conversion_goal_campaign_config_service", + "ConversionGoalCampaignConfigServiceTransport": "google.ads.googleads.v15.services.services.conversion_goal_campaign_config_service.transports", + "ConversionGoalCampaignConfigServiceGrpcTransport": "google.ads.googleads.v15.services.services.conversion_goal_campaign_config_service.transports", + "ConversionUploadServiceClient": "google.ads.googleads.v15.services.services.conversion_upload_service", + "ConversionUploadServiceTransport": "google.ads.googleads.v15.services.services.conversion_upload_service.transports", + "ConversionUploadServiceGrpcTransport": "google.ads.googleads.v15.services.services.conversion_upload_service.transports", + "ConversionValueRuleServiceClient": "google.ads.googleads.v15.services.services.conversion_value_rule_service", + "ConversionValueRuleServiceTransport": "google.ads.googleads.v15.services.services.conversion_value_rule_service.transports", + "ConversionValueRuleServiceGrpcTransport": "google.ads.googleads.v15.services.services.conversion_value_rule_service.transports", + "ConversionValueRuleSetServiceClient": "google.ads.googleads.v15.services.services.conversion_value_rule_set_service", + "ConversionValueRuleSetServiceTransport": "google.ads.googleads.v15.services.services.conversion_value_rule_set_service.transports", + "ConversionValueRuleSetServiceGrpcTransport": "google.ads.googleads.v15.services.services.conversion_value_rule_set_service.transports", + "CustomAudienceServiceClient": "google.ads.googleads.v15.services.services.custom_audience_service", + "CustomAudienceServiceTransport": "google.ads.googleads.v15.services.services.custom_audience_service.transports", + "CustomAudienceServiceGrpcTransport": "google.ads.googleads.v15.services.services.custom_audience_service.transports", + "CustomConversionGoalServiceClient": "google.ads.googleads.v15.services.services.custom_conversion_goal_service", + "CustomConversionGoalServiceTransport": "google.ads.googleads.v15.services.services.custom_conversion_goal_service.transports", + "CustomConversionGoalServiceGrpcTransport": "google.ads.googleads.v15.services.services.custom_conversion_goal_service.transports", + "CustomerAssetServiceClient": "google.ads.googleads.v15.services.services.customer_asset_service", + "CustomerAssetServiceTransport": "google.ads.googleads.v15.services.services.customer_asset_service.transports", + "CustomerAssetServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_asset_service.transports", + "CustomerAssetSetServiceClient": "google.ads.googleads.v15.services.services.customer_asset_set_service", + "CustomerAssetSetServiceTransport": "google.ads.googleads.v15.services.services.customer_asset_set_service.transports", + "CustomerAssetSetServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_asset_set_service.transports", + "CustomerClientLinkServiceClient": "google.ads.googleads.v15.services.services.customer_client_link_service", + "CustomerClientLinkServiceTransport": "google.ads.googleads.v15.services.services.customer_client_link_service.transports", + "CustomerClientLinkServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_client_link_service.transports", + "CustomerConversionGoalServiceClient": "google.ads.googleads.v15.services.services.customer_conversion_goal_service", + "CustomerConversionGoalServiceTransport": "google.ads.googleads.v15.services.services.customer_conversion_goal_service.transports", + "CustomerConversionGoalServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_conversion_goal_service.transports", + "CustomerCustomizerServiceClient": "google.ads.googleads.v15.services.services.customer_customizer_service", + "CustomerCustomizerServiceTransport": "google.ads.googleads.v15.services.services.customer_customizer_service.transports", + "CustomerCustomizerServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_customizer_service.transports", + "CustomerExtensionSettingServiceClient": "google.ads.googleads.v15.services.services.customer_extension_setting_service", + "CustomerExtensionSettingServiceTransport": "google.ads.googleads.v15.services.services.customer_extension_setting_service.transports", + "CustomerExtensionSettingServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_extension_setting_service.transports", + "CustomerFeedServiceClient": "google.ads.googleads.v15.services.services.customer_feed_service", + "CustomerFeedServiceTransport": "google.ads.googleads.v15.services.services.customer_feed_service.transports", + "CustomerFeedServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_feed_service.transports", + "CustomerLabelServiceClient": "google.ads.googleads.v15.services.services.customer_label_service", + "CustomerLabelServiceTransport": "google.ads.googleads.v15.services.services.customer_label_service.transports", + "CustomerLabelServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_label_service.transports", + "CustomerLifecycleGoalServiceClient": "google.ads.googleads.v15.services.services.customer_lifecycle_goal_service", + "CustomerLifecycleGoalServiceTransport": "google.ads.googleads.v15.services.services.customer_lifecycle_goal_service.transports", + "CustomerLifecycleGoalServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_lifecycle_goal_service.transports", + "CustomerManagerLinkServiceClient": "google.ads.googleads.v15.services.services.customer_manager_link_service", + "CustomerManagerLinkServiceTransport": "google.ads.googleads.v15.services.services.customer_manager_link_service.transports", + "CustomerManagerLinkServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_manager_link_service.transports", + "CustomerNegativeCriterionServiceClient": "google.ads.googleads.v15.services.services.customer_negative_criterion_service", + "CustomerNegativeCriterionServiceTransport": "google.ads.googleads.v15.services.services.customer_negative_criterion_service.transports", + "CustomerNegativeCriterionServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_negative_criterion_service.transports", + "CustomerServiceClient": "google.ads.googleads.v15.services.services.customer_service", + "CustomerServiceTransport": "google.ads.googleads.v15.services.services.customer_service.transports", + "CustomerServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_service.transports", + "CustomerSkAdNetworkConversionValueSchemaServiceClient": "google.ads.googleads.v15.services.services.customer_sk_ad_network_conversion_value_schema_service", + "CustomerSkAdNetworkConversionValueSchemaServiceTransport": "google.ads.googleads.v15.services.services.customer_sk_ad_network_conversion_value_schema_service.transports", + "CustomerSkAdNetworkConversionValueSchemaServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_sk_ad_network_conversion_value_schema_service.transports", + "CustomerUserAccessInvitationServiceClient": "google.ads.googleads.v15.services.services.customer_user_access_invitation_service", + "CustomerUserAccessInvitationServiceTransport": "google.ads.googleads.v15.services.services.customer_user_access_invitation_service.transports", + "CustomerUserAccessInvitationServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_user_access_invitation_service.transports", + "CustomerUserAccessServiceClient": "google.ads.googleads.v15.services.services.customer_user_access_service", + "CustomerUserAccessServiceTransport": "google.ads.googleads.v15.services.services.customer_user_access_service.transports", + "CustomerUserAccessServiceGrpcTransport": "google.ads.googleads.v15.services.services.customer_user_access_service.transports", + "CustomInterestServiceClient": "google.ads.googleads.v15.services.services.custom_interest_service", + "CustomInterestServiceTransport": "google.ads.googleads.v15.services.services.custom_interest_service.transports", + "CustomInterestServiceGrpcTransport": "google.ads.googleads.v15.services.services.custom_interest_service.transports", + "CustomizerAttributeServiceClient": "google.ads.googleads.v15.services.services.customizer_attribute_service", + "CustomizerAttributeServiceTransport": "google.ads.googleads.v15.services.services.customizer_attribute_service.transports", + "CustomizerAttributeServiceGrpcTransport": "google.ads.googleads.v15.services.services.customizer_attribute_service.transports", + "ExperimentArmServiceClient": "google.ads.googleads.v15.services.services.experiment_arm_service", + "ExperimentArmServiceTransport": "google.ads.googleads.v15.services.services.experiment_arm_service.transports", + "ExperimentArmServiceGrpcTransport": "google.ads.googleads.v15.services.services.experiment_arm_service.transports", + "ExperimentServiceClient": "google.ads.googleads.v15.services.services.experiment_service", + "ExperimentServiceTransport": "google.ads.googleads.v15.services.services.experiment_service.transports", + "ExperimentServiceGrpcTransport": "google.ads.googleads.v15.services.services.experiment_service.transports", + "ExtensionFeedItemServiceClient": "google.ads.googleads.v15.services.services.extension_feed_item_service", + "ExtensionFeedItemServiceTransport": "google.ads.googleads.v15.services.services.extension_feed_item_service.transports", + "ExtensionFeedItemServiceGrpcTransport": "google.ads.googleads.v15.services.services.extension_feed_item_service.transports", + "FeedItemServiceClient": "google.ads.googleads.v15.services.services.feed_item_service", + "FeedItemServiceTransport": "google.ads.googleads.v15.services.services.feed_item_service.transports", + "FeedItemServiceGrpcTransport": "google.ads.googleads.v15.services.services.feed_item_service.transports", + "FeedItemSetLinkServiceClient": "google.ads.googleads.v15.services.services.feed_item_set_link_service", + "FeedItemSetLinkServiceTransport": "google.ads.googleads.v15.services.services.feed_item_set_link_service.transports", + "FeedItemSetLinkServiceGrpcTransport": "google.ads.googleads.v15.services.services.feed_item_set_link_service.transports", + "FeedItemSetServiceClient": "google.ads.googleads.v15.services.services.feed_item_set_service", + "FeedItemSetServiceTransport": "google.ads.googleads.v15.services.services.feed_item_set_service.transports", + "FeedItemSetServiceGrpcTransport": "google.ads.googleads.v15.services.services.feed_item_set_service.transports", + "FeedItemTargetServiceClient": "google.ads.googleads.v15.services.services.feed_item_target_service", + "FeedItemTargetServiceTransport": "google.ads.googleads.v15.services.services.feed_item_target_service.transports", + "FeedItemTargetServiceGrpcTransport": "google.ads.googleads.v15.services.services.feed_item_target_service.transports", + "FeedMappingServiceClient": "google.ads.googleads.v15.services.services.feed_mapping_service", + "FeedMappingServiceTransport": "google.ads.googleads.v15.services.services.feed_mapping_service.transports", + "FeedMappingServiceGrpcTransport": "google.ads.googleads.v15.services.services.feed_mapping_service.transports", + "FeedServiceClient": "google.ads.googleads.v15.services.services.feed_service", + "FeedServiceTransport": "google.ads.googleads.v15.services.services.feed_service.transports", + "FeedServiceGrpcTransport": "google.ads.googleads.v15.services.services.feed_service.transports", + "GeoTargetConstantServiceClient": "google.ads.googleads.v15.services.services.geo_target_constant_service", + "GeoTargetConstantServiceTransport": "google.ads.googleads.v15.services.services.geo_target_constant_service.transports", + "GeoTargetConstantServiceGrpcTransport": "google.ads.googleads.v15.services.services.geo_target_constant_service.transports", + "GoogleAdsFieldServiceClient": "google.ads.googleads.v15.services.services.google_ads_field_service", + "GoogleAdsFieldServiceTransport": "google.ads.googleads.v15.services.services.google_ads_field_service.transports", + "GoogleAdsFieldServiceGrpcTransport": "google.ads.googleads.v15.services.services.google_ads_field_service.transports", + "GoogleAdsServiceClient": "google.ads.googleads.v15.services.services.google_ads_service", + "GoogleAdsServiceTransport": "google.ads.googleads.v15.services.services.google_ads_service.transports", + "GoogleAdsServiceGrpcTransport": "google.ads.googleads.v15.services.services.google_ads_service.transports", + "InvoiceServiceClient": "google.ads.googleads.v15.services.services.invoice_service", + "InvoiceServiceTransport": "google.ads.googleads.v15.services.services.invoice_service.transports", + "InvoiceServiceGrpcTransport": "google.ads.googleads.v15.services.services.invoice_service.transports", + "KeywordPlanAdGroupKeywordServiceClient": "google.ads.googleads.v15.services.services.keyword_plan_ad_group_keyword_service", + "KeywordPlanAdGroupKeywordServiceTransport": "google.ads.googleads.v15.services.services.keyword_plan_ad_group_keyword_service.transports", + "KeywordPlanAdGroupKeywordServiceGrpcTransport": "google.ads.googleads.v15.services.services.keyword_plan_ad_group_keyword_service.transports", + "KeywordPlanAdGroupServiceClient": "google.ads.googleads.v15.services.services.keyword_plan_ad_group_service", + "KeywordPlanAdGroupServiceTransport": "google.ads.googleads.v15.services.services.keyword_plan_ad_group_service.transports", + "KeywordPlanAdGroupServiceGrpcTransport": "google.ads.googleads.v15.services.services.keyword_plan_ad_group_service.transports", + "KeywordPlanCampaignKeywordServiceClient": "google.ads.googleads.v15.services.services.keyword_plan_campaign_keyword_service", + "KeywordPlanCampaignKeywordServiceTransport": "google.ads.googleads.v15.services.services.keyword_plan_campaign_keyword_service.transports", + "KeywordPlanCampaignKeywordServiceGrpcTransport": "google.ads.googleads.v15.services.services.keyword_plan_campaign_keyword_service.transports", + "KeywordPlanCampaignServiceClient": "google.ads.googleads.v15.services.services.keyword_plan_campaign_service", + "KeywordPlanCampaignServiceTransport": "google.ads.googleads.v15.services.services.keyword_plan_campaign_service.transports", + "KeywordPlanCampaignServiceGrpcTransport": "google.ads.googleads.v15.services.services.keyword_plan_campaign_service.transports", + "KeywordPlanIdeaServiceClient": "google.ads.googleads.v15.services.services.keyword_plan_idea_service", + "KeywordPlanIdeaServiceTransport": "google.ads.googleads.v15.services.services.keyword_plan_idea_service.transports", + "KeywordPlanIdeaServiceGrpcTransport": "google.ads.googleads.v15.services.services.keyword_plan_idea_service.transports", + "KeywordPlanServiceClient": "google.ads.googleads.v15.services.services.keyword_plan_service", + "KeywordPlanServiceTransport": "google.ads.googleads.v15.services.services.keyword_plan_service.transports", + "KeywordPlanServiceGrpcTransport": "google.ads.googleads.v15.services.services.keyword_plan_service.transports", + "KeywordThemeConstantServiceClient": "google.ads.googleads.v15.services.services.keyword_theme_constant_service", + "KeywordThemeConstantServiceTransport": "google.ads.googleads.v15.services.services.keyword_theme_constant_service.transports", + "KeywordThemeConstantServiceGrpcTransport": "google.ads.googleads.v15.services.services.keyword_theme_constant_service.transports", + "LabelServiceClient": "google.ads.googleads.v15.services.services.label_service", + "LabelServiceTransport": "google.ads.googleads.v15.services.services.label_service.transports", + "LabelServiceGrpcTransport": "google.ads.googleads.v15.services.services.label_service.transports", + "OfflineUserDataJobServiceClient": "google.ads.googleads.v15.services.services.offline_user_data_job_service", + "OfflineUserDataJobServiceTransport": "google.ads.googleads.v15.services.services.offline_user_data_job_service.transports", + "OfflineUserDataJobServiceGrpcTransport": "google.ads.googleads.v15.services.services.offline_user_data_job_service.transports", + "PaymentsAccountServiceClient": "google.ads.googleads.v15.services.services.payments_account_service", + "PaymentsAccountServiceTransport": "google.ads.googleads.v15.services.services.payments_account_service.transports", + "PaymentsAccountServiceGrpcTransport": "google.ads.googleads.v15.services.services.payments_account_service.transports", + "ProductLinkInvitationServiceClient": "google.ads.googleads.v15.services.services.product_link_invitation_service", + "ProductLinkInvitationServiceTransport": "google.ads.googleads.v15.services.services.product_link_invitation_service.transports", + "ProductLinkInvitationServiceGrpcTransport": "google.ads.googleads.v15.services.services.product_link_invitation_service.transports", + "ProductLinkServiceClient": "google.ads.googleads.v15.services.services.product_link_service", + "ProductLinkServiceTransport": "google.ads.googleads.v15.services.services.product_link_service.transports", + "ProductLinkServiceGrpcTransport": "google.ads.googleads.v15.services.services.product_link_service.transports", + "ReachPlanServiceClient": "google.ads.googleads.v15.services.services.reach_plan_service", + "ReachPlanServiceTransport": "google.ads.googleads.v15.services.services.reach_plan_service.transports", + "ReachPlanServiceGrpcTransport": "google.ads.googleads.v15.services.services.reach_plan_service.transports", + "RecommendationServiceClient": "google.ads.googleads.v15.services.services.recommendation_service", + "RecommendationServiceTransport": "google.ads.googleads.v15.services.services.recommendation_service.transports", + "RecommendationServiceGrpcTransport": "google.ads.googleads.v15.services.services.recommendation_service.transports", + "RecommendationSubscriptionServiceClient": "google.ads.googleads.v15.services.services.recommendation_subscription_service", + "RecommendationSubscriptionServiceTransport": "google.ads.googleads.v15.services.services.recommendation_subscription_service.transports", + "RecommendationSubscriptionServiceGrpcTransport": "google.ads.googleads.v15.services.services.recommendation_subscription_service.transports", + "RemarketingActionServiceClient": "google.ads.googleads.v15.services.services.remarketing_action_service", + "RemarketingActionServiceTransport": "google.ads.googleads.v15.services.services.remarketing_action_service.transports", + "RemarketingActionServiceGrpcTransport": "google.ads.googleads.v15.services.services.remarketing_action_service.transports", + "SharedCriterionServiceClient": "google.ads.googleads.v15.services.services.shared_criterion_service", + "SharedCriterionServiceTransport": "google.ads.googleads.v15.services.services.shared_criterion_service.transports", + "SharedCriterionServiceGrpcTransport": "google.ads.googleads.v15.services.services.shared_criterion_service.transports", + "SharedSetServiceClient": "google.ads.googleads.v15.services.services.shared_set_service", + "SharedSetServiceTransport": "google.ads.googleads.v15.services.services.shared_set_service.transports", + "SharedSetServiceGrpcTransport": "google.ads.googleads.v15.services.services.shared_set_service.transports", + "SmartCampaignSettingServiceClient": "google.ads.googleads.v15.services.services.smart_campaign_setting_service", + "SmartCampaignSettingServiceTransport": "google.ads.googleads.v15.services.services.smart_campaign_setting_service.transports", + "SmartCampaignSettingServiceGrpcTransport": "google.ads.googleads.v15.services.services.smart_campaign_setting_service.transports", + "SmartCampaignSuggestServiceClient": "google.ads.googleads.v15.services.services.smart_campaign_suggest_service", + "SmartCampaignSuggestServiceTransport": "google.ads.googleads.v15.services.services.smart_campaign_suggest_service.transports", + "SmartCampaignSuggestServiceGrpcTransport": "google.ads.googleads.v15.services.services.smart_campaign_suggest_service.transports", + "ThirdPartyAppAnalyticsLinkServiceClient": "google.ads.googleads.v15.services.services.third_party_app_analytics_link_service", + "ThirdPartyAppAnalyticsLinkServiceTransport": "google.ads.googleads.v15.services.services.third_party_app_analytics_link_service.transports", + "ThirdPartyAppAnalyticsLinkServiceGrpcTransport": "google.ads.googleads.v15.services.services.third_party_app_analytics_link_service.transports", + "TravelAssetSuggestionServiceClient": "google.ads.googleads.v15.services.services.travel_asset_suggestion_service", + "TravelAssetSuggestionServiceTransport": "google.ads.googleads.v15.services.services.travel_asset_suggestion_service.transports", + "TravelAssetSuggestionServiceGrpcTransport": "google.ads.googleads.v15.services.services.travel_asset_suggestion_service.transports", + "UserDataServiceClient": "google.ads.googleads.v15.services.services.user_data_service", + "UserDataServiceTransport": "google.ads.googleads.v15.services.services.user_data_service.transports", + "UserDataServiceGrpcTransport": "google.ads.googleads.v15.services.services.user_data_service.transports", + "UserListServiceClient": "google.ads.googleads.v15.services.services.user_list_service", + "UserListServiceTransport": "google.ads.googleads.v15.services.services.user_list_service.transports", + "UserListServiceGrpcTransport": "google.ads.googleads.v15.services.services.user_list_service.transports", +} + + +# Background on how this behaves: https://www.python.org/dev/peps/pep-0562/ +def __getattr__(name): # Requires Python >= 3.7 + if name == "__all__": + all_names = globals()["__all__"] = sorted(_lazy_type_to_package_map) + return all_names + elif name in _lazy_type_to_package_map: + module = importlib.import_module(f"{_lazy_type_to_package_map[name]}") + klass = getattr(module, name) + globals()[name] = klass + return klass + else: + raise AttributeError(f"unknown type {name!r}.") + + +def __dir__(): + return globals().get("__all__") or __getattr__("__all__") diff --git a/google/ads/googleads/v15/common/__init__.py b/google/ads/googleads/v15/common/__init__.py new file mode 100644 index 000000000..44cc9ff1c --- /dev/null +++ b/google/ads/googleads/v15/common/__init__.py @@ -0,0 +1,315 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +__all__ = ( + "ActivityCountryInfo", + "ActivityIdInfo", + "ActivityRatingInfo", + "AdAssetPolicySummary", + "AdCallToActionAsset", + "AdDiscoveryCarouselCardAsset", + "AdImageAsset", + "AdMediaBundleAsset", + "AdScheduleInfo", + "AdTextAsset", + "AdVideoAsset", + "AddressInfo", + "AffiliateLocationFeedItem", + "AgeDimension", + "AgeRangeInfo", + "AgeSegment", + "AppAdInfo", + "AppEngagementAdInfo", + "AppFeedItem", + "AppPaymentModelInfo", + "AppPreRegistrationAdInfo", + "AssetDisapproved", + "AssetInteractionTarget", + "AssetLinkPrimaryStatusDetails", + "AssetUsage", + "AudienceDimension", + "AudienceExclusionDimension", + "AudienceInfo", + "AudienceSegment", + "AudienceSegmentDimension", + "BasicUserListInfo", + "BookOnGoogleAsset", + "BrandInfo", + "BrandListInfo", + "BudgetCampaignAssociationStatus", + "BudgetSimulationPoint", + "BudgetSimulationPointList", + "BusinessNameFilter", + "BusinessProfileBusinessNameFilter", + "BusinessProfileLocation", + "BusinessProfileLocationGroup", + "BusinessProfileLocationSet", + "CallAdInfo", + "CallAsset", + "CallFeedItem", + "CallToActionAsset", + "CalloutAsset", + "CalloutFeedItem", + "CarrierInfo", + "ChainFilter", + "ChainLocationGroup", + "ChainSet", + "ClickLocation", + "CombinedAudienceInfo", + "Commission", + "ConceptGroup", + "Consent", + "ContentLabelInfo", + "CpcBidSimulationPoint", + "CpcBidSimulationPointList", + "CpvBidSimulationPoint", + "CpvBidSimulationPointList", + "CriterionCategoryAvailability", + "CriterionCategoryChannelAvailability", + "CriterionCategoryLocaleAvailability", + "CrmBasedUserListInfo", + "CustomAffinityInfo", + "CustomAudienceInfo", + "CustomAudienceSegment", + "CustomIntentInfo", + "CustomParameter", + "CustomerMatchUserListMetadata", + "CustomizerValue", + "DateRange", + "DetailedDemographicSegment", + "DeviceInfo", + "DiscoveryCarouselAdInfo", + "DiscoveryCarouselCardAsset", + "DiscoveryMultiAssetAdInfo", + "DiscoveryVideoResponsiveAdInfo", + "DisplayUploadAdInfo", + "DynamicAffiliateLocationSetFilter", + "DynamicBusinessProfileLocationGroupFilter", + "DynamicCustomAsset", + "DynamicEducationAsset", + "DynamicFlightsAsset", + "DynamicHotelsAndRentalsAsset", + "DynamicJobsAsset", + "DynamicLocalAsset", + "DynamicLocationSetFilter", + "DynamicRealEstateAsset", + "DynamicTravelAsset", + "EnhancedCpc", + "EventAttribute", + "EventItemAttribute", + "ExclusionSegment", + "ExpandedDynamicSearchAdInfo", + "ExpandedTextAdInfo", + "FinalAppUrl", + "FlexibleRuleOperandInfo", + "FlexibleRuleUserListInfo", + "FrequencyCapEntry", + "FrequencyCapKey", + "GenderDimension", + "GenderInfo", + "GeoPointInfo", + "HistoricalMetricsOptions", + "HotelAdInfo", + "HotelAdvanceBookingWindowInfo", + "HotelCalloutAsset", + "HotelCalloutFeedItem", + "HotelCheckInDateRangeInfo", + "HotelCheckInDayInfo", + "HotelCityInfo", + "HotelClassInfo", + "HotelCountryRegionInfo", + "HotelDateSelectionTypeInfo", + "HotelIdInfo", + "HotelLengthOfStayInfo", + "HotelPropertyAsset", + "HotelStateInfo", + "HouseholdIncomeDimension", + "ImageAdInfo", + "ImageAsset", + "ImageDimension", + "ImageFeedItem", + "InFeedVideoAdInfo", + "IncomeRangeInfo", + "InteractionTypeInfo", + "IpBlockInfo", + "ItemAttribute", + "Keyword", + "KeywordAnnotations", + "KeywordConcept", + "KeywordInfo", + "KeywordPlanAggregateMetricResults", + "KeywordPlanAggregateMetrics", + "KeywordPlanDeviceSearches", + "KeywordPlanHistoricalMetrics", + "KeywordThemeInfo", + "LanguageInfo", + "LeadFormAsset", + "LeadFormCustomQuestionField", + "LeadFormDeliveryMethod", + "LeadFormField", + "LeadFormSingleChoiceAnswers", + "LegacyAppInstallAdInfo", + "LegacyResponsiveDisplayAdInfo", + "LifeEventSegment", + "LifecycleGoalValueSettings", + "ListingDimensionInfo", + "ListingDimensionPath", + "ListingGroupInfo", + "ListingScopeInfo", + "LocalAdInfo", + "LocalServiceIdInfo", + "LocalServicesDocumentReadOnly", + "LocationAsset", + "LocationFeedItem", + "LocationGroupInfo", + "LocationInfo", + "LocationSet", + "LogicalUserListInfo", + "LogicalUserListOperandInfo", + "LookalikeUserListInfo", + "ManualCpa", + "ManualCpc", + "ManualCpm", + "ManualCpv", + "MapsLocationInfo", + "MapsLocationSet", + "MatchingFunction", + "MaximizeConversionValue", + "MaximizeConversions", + "MediaBundleAsset", + "MetricGoal", + "Metrics", + "MobileAppAsset", + "MobileAppCategoryInfo", + "MobileApplicationInfo", + "MobileDeviceInfo", + "Money", + "MonthlySearchVolume", + "NegativeKeywordListInfo", + "OfflineUserAddressInfo", + "Operand", + "OperatingSystemVersionInfo", + "PageFeedAsset", + "ParentalStatusDimension", + "ParentalStatusInfo", + "PercentCpc", + "PercentCpcBidSimulationPoint", + "PercentCpcBidSimulationPointList", + "PlacementInfo", + "PolicySummary", + "PolicyTopicConstraint", + "PolicyTopicEntry", + "PolicyTopicEvidence", + "PolicyValidationParameter", + "PolicyViolationKey", + "PriceAsset", + "PriceFeedItem", + "PriceOffer", + "PriceOffering", + "ProductBrandInfo", + "ProductCategoryInfo", + "ProductChannelExclusivityInfo", + "ProductChannelInfo", + "ProductConditionInfo", + "ProductCustomAttributeInfo", + "ProductGroupingInfo", + "ProductItemIdInfo", + "ProductLabelsInfo", + "ProductLegacyConditionInfo", + "ProductTypeFullInfo", + "ProductTypeInfo", + "PromotionAsset", + "PromotionFeedItem", + "ProximityInfo", + "RealTimeBiddingSetting", + "ResponsiveDisplayAdControlSpec", + "ResponsiveDisplayAdInfo", + "ResponsiveSearchAdInfo", + "RuleBasedUserListInfo", + "SearchThemeInfo", + "SearchVolumeRange", + "Segments", + "ShoppingComparisonListingAdInfo", + "ShoppingLoyalty", + "ShoppingProductAdInfo", + "ShoppingSmartAdInfo", + "SimilarUserListInfo", + "SitelinkAsset", + "SitelinkFeedItem", + "SkAdNetworkSourceApp", + "SmartCampaignAdInfo", + "StoreAttribute", + "StoreSalesMetadata", + "StoreSalesThirdPartyMetadata", + "StructuredSnippetAsset", + "StructuredSnippetFeedItem", + "TagSnippet", + "TargetCpa", + "TargetCpaSimulationPoint", + "TargetCpaSimulationPointList", + "TargetCpm", + "TargetCpmTargetFrequencyGoal", + "TargetImpressionShare", + "TargetImpressionShareSimulationPoint", + "TargetImpressionShareSimulationPointList", + "TargetRestriction", + "TargetRestrictionOperation", + "TargetRoas", + "TargetRoasSimulationPoint", + "TargetRoasSimulationPointList", + "TargetSpend", + "TargetingSetting", + "TextAdInfo", + "TextAsset", + "TextLabel", + "TextMessageFeedItem", + "TopicInfo", + "TransactionAttribute", + "TravelAdInfo", + "UnknownListingDimensionInfo", + "UrlCollection", + "UserAttribute", + "UserData", + "UserIdentifier", + "UserInterestInfo", + "UserInterestSegment", + "UserListActionInfo", + "UserListDateRuleItemInfo", + "UserListInfo", + "UserListLogicalRuleInfo", + "UserListNumberRuleItemInfo", + "UserListRuleInfo", + "UserListRuleItemGroupInfo", + "UserListRuleItemInfo", + "UserListSegment", + "UserListStringRuleItemInfo", + "Value", + "VideoAdInfo", + "VideoBumperInStreamAdInfo", + "VideoNonSkippableInStreamAdInfo", + "VideoOutstreamAdInfo", + "VideoResponsiveAdInfo", + "VideoTrueViewInStreamAdInfo", + "WebhookDelivery", + "WebpageConditionInfo", + "WebpageInfo", + "WebpageSampleInfo", + "YearMonth", + "YearMonthRange", + "YouTubeChannelInfo", + "YouTubeVideoInfo", + "YoutubeVideoAsset", +) diff --git a/google/ads/googleads/v15/common/services/__init__.py b/google/ads/googleads/v15/common/services/__init__.py new file mode 100644 index 000000000..89a37dc92 --- /dev/null +++ b/google/ads/googleads/v15/common/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/v15/common/types/__init__.py b/google/ads/googleads/v15/common/types/__init__.py new file mode 100644 index 000000000..89a37dc92 --- /dev/null +++ b/google/ads/googleads/v15/common/types/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/v15/common/types/ad_asset.py b/google/ads/googleads/v15/common/types/ad_asset.py new file mode 100644 index 000000000..db9406e0d --- /dev/null +++ b/google/ads/googleads/v15/common/types/ad_asset.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import asset_policy +from google.ads.googleads.v15.enums.types import ( + asset_performance_label as gage_asset_performance_label, +) +from google.ads.googleads.v15.enums.types import served_asset_field_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + manifest={ + "AdTextAsset", + "AdImageAsset", + "AdVideoAsset", + "AdMediaBundleAsset", + "AdDiscoveryCarouselCardAsset", + "AdCallToActionAsset", + }, +) + + +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.v15.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.v15.enums.types.AssetPerformanceLabelEnum.AssetPerformanceLabel): + The performance label of this text asset. + policy_summary_info (google.ads.googleads.v15.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``. + """ + + asset: str = proto.Field( + proto.STRING, + number=2, + 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 AdDiscoveryCarouselCardAsset(proto.Message): + r"""A discovery 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/common/types/ad_type_infos.py b/google/ads/googleads/v15/common/types/ad_type_infos.py new file mode 100644 index 000000000..c43f39bba --- /dev/null +++ b/google/ads/googleads/v15/common/types/ad_type_infos.py @@ -0,0 +1,1802 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import ad_asset +from google.ads.googleads.v15.enums.types import call_conversion_reporting_state +from google.ads.googleads.v15.enums.types import display_ad_format_setting +from google.ads.googleads.v15.enums.types import ( + display_upload_product_type as gage_display_upload_product_type, +) +from google.ads.googleads.v15.enums.types import legacy_app_install_ad_app_store +from google.ads.googleads.v15.enums.types import mime_type as gage_mime_type +from google.ads.googleads.v15.enums.types import video_thumbnail + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + manifest={ + "TextAdInfo", + "ExpandedTextAdInfo", + "ExpandedDynamicSearchAdInfo", + "HotelAdInfo", + "TravelAdInfo", + "ShoppingSmartAdInfo", + "ShoppingProductAdInfo", + "ShoppingComparisonListingAdInfo", + "ImageAdInfo", + "VideoBumperInStreamAdInfo", + "VideoNonSkippableInStreamAdInfo", + "VideoTrueViewInStreamAdInfo", + "VideoOutstreamAdInfo", + "InFeedVideoAdInfo", + "VideoAdInfo", + "VideoResponsiveAdInfo", + "ResponsiveSearchAdInfo", + "LegacyResponsiveDisplayAdInfo", + "AppAdInfo", + "AppEngagementAdInfo", + "AppPreRegistrationAdInfo", + "LegacyAppInstallAdInfo", + "ResponsiveDisplayAdInfo", + "LocalAdInfo", + "DisplayUploadAdInfo", + "ResponsiveDisplayAdControlSpec", + "SmartCampaignAdInfo", + "CallAdInfo", + "DiscoveryMultiAssetAdInfo", + "DiscoveryCarouselAdInfo", + "DiscoveryVideoResponsiveAdInfo", + }, +) + + +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. + .. _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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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 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.v15.common.types.AdVideoAsset): + The YouTube video assets used for the ad. + in_stream (google.ads.googleads.v15.common.types.VideoTrueViewInStreamAdInfo): + Video TrueView in-stream ad format. + + This field is a member of `oneof`_ ``format``. + bumper (google.ads.googleads.v15.common.types.VideoBumperInStreamAdInfo): + Video bumper in-stream ad format. + + This field is a member of `oneof`_ ``format``. + out_stream (google.ads.googleads.v15.common.types.VideoOutstreamAdInfo): + Video out-stream ad format. + + This field is a member of `oneof`_ ``format``. + non_skippable (google.ads.googleads.v15.common.types.VideoNonSkippableInStreamAdInfo): + Video non-skippable in-stream ad format. + + This field is a member of `oneof`_ ``format``. + in_feed (google.ads.googleads.v15.common.types.InFeedVideoAdInfo): + In-feed video 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", + ) + + +class VideoResponsiveAdInfo(proto.Message): + r"""A video responsive ad. + Attributes: + headlines (MutableSequence[google.ads.googleads.v15.common.types.AdTextAsset]): + List of text assets used for the short + headline, for example, the "Call To Action" + banner. Currently, only a single value for the + short headline is supported. + long_headlines (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.common.types.AdVideoAsset]): + List of YouTube video assets used for the ad. + Currently, only a single value for the YouTube + video asset is supported. + companion_banners (MutableSequence[google.ads.googleads.v15.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, + ) + 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.v15.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.v15.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.v15.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.v15.common.types.AdTextAsset): + Mandatory ad text. + headlines (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.common.types.AdImageAsset]): + List of image assets that may be displayed + with the ad. + youtube_videos (MutableSequence[google.ads.googleads.v15.common.types.AdVideoAsset]): + List of YouTube video assets that may be + displayed with the ad. + html5_media_bundles (MutableSequence[google.ads.googleads.v15.common.types.AdMediaBundleAsset]): + List of media bundle assets 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, + ) + + +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.v15.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.v15.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.v15.common.types.AdImageAsset]): + List of image assets that may be displayed + with the ad. + videos (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.common.types.AdImageAsset]): + List of image asset IDs whose images may be + displayed with the ad. + youtube_videos (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.common.types.AdTextAsset): + A required long format headline. The maximum + length is 90 characters. + descriptions (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.enums.types.DisplayAdFormatSettingEnum.DisplayAdFormatSetting): + Specifies which format the ad will be served in. Default is + ALL_FORMATS. + control_spec (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.enums.types.DisplayUploadProductTypeEnum.DisplayUploadProductType): + The product type of this ad. See comments on + the enum for details. + media_bundle (google.ads.googleads.v15.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.v15.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.v15.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 CallAdInfo(proto.Message): + r"""A call ad. + Attributes: + country_code (str): + The country code in the ad. + phone_number (str): + The phone number in the ad. + business_name (str): + The business name in the ad. + headline1 (str): + First headline in the ad. + headline2 (str): + Second headline in the ad. + description1 (str): + The first line of the ad's description. + description2 (str): + The second line of the ad's description. + call_tracked (bool): + Whether to enable call tracking for the + creative. Enabling call tracking also enables + call conversions. + disable_call_conversion (bool): + Whether to disable call conversion for the creative. If set + to ``true``, disables call conversions even when + ``call_tracked`` is ``true``. If ``call_tracked`` is + ``false``, this field is ignored. + phone_number_verification_url (str): + The URL to be used for phone number + verification. + 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_tracked`` is set to ``true``. Otherwise + this field is ignored. + conversion_reporting_state (google.ads.googleads.v15.enums.types.CallConversionReportingStateEnum.CallConversionReportingState): + The call conversion behavior of this call ad. + It can use its own call conversion setting, + inherit the account level setting, or be + disabled. + path1 (str): + First part of text that can be appended to + the URL in the ad. Optional. + 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. + Optional. + """ + + country_code: str = proto.Field( + proto.STRING, + number=1, + ) + phone_number: str = proto.Field( + proto.STRING, + number=2, + ) + business_name: str = proto.Field( + proto.STRING, + number=3, + ) + headline1: str = proto.Field( + proto.STRING, + number=11, + ) + headline2: str = proto.Field( + proto.STRING, + number=12, + ) + description1: str = proto.Field( + proto.STRING, + number=4, + ) + description2: str = proto.Field( + proto.STRING, + number=5, + ) + call_tracked: bool = proto.Field( + proto.BOOL, + number=6, + ) + disable_call_conversion: bool = proto.Field( + proto.BOOL, + number=7, + ) + phone_number_verification_url: str = proto.Field( + proto.STRING, + number=8, + ) + conversion_action: str = proto.Field( + proto.STRING, + number=9, + ) + conversion_reporting_state: call_conversion_reporting_state.CallConversionReportingStateEnum.CallConversionReportingState = proto.Field( + proto.ENUM, + number=10, + enum=call_conversion_reporting_state.CallConversionReportingStateEnum.CallConversionReportingState, + ) + path1: str = proto.Field( + proto.STRING, + number=13, + ) + path2: str = proto.Field( + proto.STRING, + number=14, + ) + + +class DiscoveryMultiAssetAdInfo(proto.Message): + r"""A discovery 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.v15.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`` and + ``portrait_marketing_images`` the maximum is 20. + square_marketing_images (MutableSequence[google.ads.googleads.v15.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`` and ``portrait_marketing_images`` the + maximum is 20. + portrait_marketing_images (MutableSequence[google.ads.googleads.v15.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`` and ``square_marketing_images`` + the maximum is 20. + logo_images (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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``. + lead_form_only (bool): + Boolean option that indicates if this ad must + be served with lead form. + + This field is a member of `oneof`_ ``_lead_form_only``. + """ + + 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, + ) + 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, + ) + lead_form_only: bool = proto.Field( + proto.BOOL, + number=9, + optional=True, + ) + + +class DiscoveryCarouselAdInfo(proto.Message): + r"""A discovery carousel ad. + Attributes: + business_name (str): + Required. The Advertiser/brand name. + logo_image (google.ads.googleads.v15.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.v15.common.types.AdTextAsset): + Required. Headline of the ad. + description (google.ads.googleads.v15.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.v15.common.types.AdDiscoveryCarouselCardAsset]): + 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.AdDiscoveryCarouselCardAsset + ] = proto.RepeatedField( + proto.MESSAGE, + number=6, + message=ad_asset.AdDiscoveryCarouselCardAsset, + ) + + +class DiscoveryVideoResponsiveAdInfo(proto.Message): + r"""A discovery video responsive ad. + Attributes: + headlines (MutableSequence[google.ads.googleads.v15.common.types.AdTextAsset]): + List of text assets used for the short + headline, for example, the "Call To Action" + banner. + long_headlines (MutableSequence[google.ads.googleads.v15.common.types.AdTextAsset]): + List of text assets used for the long + headline. + descriptions (MutableSequence[google.ads.googleads.v15.common.types.AdTextAsset]): + List of text assets used for the description. + videos (MutableSequence[google.ads.googleads.v15.common.types.AdVideoAsset]): + List of YouTube video assets used for the ad. + logo_images (MutableSequence[google.ads.googleads.v15.common.types.AdImageAsset]): + 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%). + 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.v15.common.types.AdTextAsset): + Required. The advertiser/brand name. + call_to_actions (MutableSequence[google.ads.googleads.v15.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, + ) + 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/common/types/asset_policy.py b/google/ads/googleads/v15/common/types/asset_policy.py new file mode 100644 index 000000000..4a760091a --- /dev/null +++ b/google/ads/googleads/v15/common/types/asset_policy.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import policy +from google.ads.googleads.v15.enums.types import asset_link_primary_status +from google.ads.googleads.v15.enums.types import ( + asset_link_primary_status_reason, +) +from google.ads.googleads.v15.enums.types import ( + asset_offline_evaluation_error_reasons, +) +from google.ads.googleads.v15.enums.types import policy_approval_status +from google.ads.googleads.v15.enums.types import policy_review_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.common.types.PolicyTopicEntry]): + The list of policy findings for this asset. + review_status (google.ads.googleads.v15.enums.types.PolicyReviewStatusEnum.PolicyReviewStatus): + Where in the review process this asset. + approval_status (google.ads.googleads.v15.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.v15.enums.types.AssetLinkPrimaryStatusReasonEnum.AssetLinkPrimaryStatusReason): + Provides the reason of this PrimaryStatus. + + This field is a member of `oneof`_ ``_reason``. + status (google.ads.googleads.v15.enums.types.AssetLinkPrimaryStatusEnum.AssetLinkPrimaryStatus): + Provides the PrimaryStatus of this status + detail. + + This field is a member of `oneof`_ ``_status``. + asset_disapproved (google.ads.googleads.v15.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.v15.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/v15/common/types/asset_set_types.py b/google/ads/googleads/v15/common/types/asset_set_types.py new file mode 100644 index 000000000..5bb599400 --- /dev/null +++ b/google/ads/googleads/v15/common/types/asset_set_types.py @@ -0,0 +1,354 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import chain_relationship_type +from google.ads.googleads.v15.enums.types import ( + location_ownership_type as gage_location_ownership_type, +) +from google.ads.googleads.v15.enums.types import location_string_filter_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.LocationOwnershipTypeEnum.LocationOwnershipType): + Required. Immutable. Location Ownership Type + (owned location or affiliate location). + business_profile_location_set (google.ads.googleads.v15.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.v15.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.v15.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.v15.enums.types.ChainRelationshipTypeEnum.ChainRelationshipType): + Required. Immutable. Relationship type the + specified chains have with this advertiser. + chains (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/common/types/asset_types.py b/google/ads/googleads/v15/common/types/asset_types.py new file mode 100644 index 000000000..248981f50 --- /dev/null +++ b/google/ads/googleads/v15/common/types/asset_types.py @@ -0,0 +1,2247 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import criteria +from google.ads.googleads.v15.common.types import feed_common +from google.ads.googleads.v15.enums.types import ( + call_conversion_reporting_state as gage_call_conversion_reporting_state, +) +from google.ads.googleads.v15.enums.types import ( + call_to_action_type as gage_call_to_action_type, +) +from google.ads.googleads.v15.enums.types import lead_form_call_to_action_type +from google.ads.googleads.v15.enums.types import lead_form_desired_intent +from google.ads.googleads.v15.enums.types import lead_form_field_user_input_type +from google.ads.googleads.v15.enums.types import ( + lead_form_post_submit_call_to_action_type, +) +from google.ads.googleads.v15.enums.types import ( + location_ownership_type as gage_location_ownership_type, +) +from google.ads.googleads.v15.enums.types import mime_type as gage_mime_type +from google.ads.googleads.v15.enums.types import mobile_app_vendor +from google.ads.googleads.v15.enums.types import price_extension_price_qualifier +from google.ads.googleads.v15.enums.types import price_extension_price_unit +from google.ads.googleads.v15.enums.types import price_extension_type +from google.ads.googleads.v15.enums.types import ( + promotion_extension_discount_modifier, +) +from google.ads.googleads.v15.enums.types import promotion_extension_occasion + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + manifest={ + "YoutubeVideoAsset", + "MediaBundleAsset", + "ImageAsset", + "ImageDimension", + "TextAsset", + "LeadFormAsset", + "LeadFormField", + "LeadFormCustomQuestionField", + "LeadFormSingleChoiceAnswers", + "LeadFormDeliveryMethod", + "WebhookDelivery", + "BookOnGoogleAsset", + "PromotionAsset", + "CalloutAsset", + "StructuredSnippetAsset", + "SitelinkAsset", + "PageFeedAsset", + "DynamicEducationAsset", + "MobileAppAsset", + "HotelCalloutAsset", + "CallAsset", + "PriceAsset", + "PriceOffering", + "CallToActionAsset", + "DynamicRealEstateAsset", + "DynamicCustomAsset", + "DynamicHotelsAndRentalsAsset", + "DynamicFlightsAsset", + "DiscoveryCarouselCardAsset", + "DynamicTravelAsset", + "DynamicLocalAsset", + "DynamicJobsAsset", + "LocationAsset", + "BusinessProfileLocation", + "HotelPropertyAsset", + }, +) + + +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.v15.enums.types.MimeTypeEnum.MimeType): + MIME type of the image asset. + full_size (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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 minimum size is 600x314 and the aspect ratio + must be 1.91:1 (+-1%). + + This field is a member of `oneof`_ ``_background_image_asset``. + desired_intent (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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. + 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.v15.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.v15.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_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, + ) + 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, + ) + + +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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.enums.types.PriceExtensionTypeEnum.PriceExtensionType): + Required. The type of the price asset. + price_qualifier (google.ads.googleads.v15.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.v15.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.v15.common.types.Money): + Required. The price value of the price + offering. + unit (google.ads.googleads.v15.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.v15.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 DiscoveryCarouselCardAsset(proto.Message): + r"""A Discovery 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.v15.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.v15.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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/common/types/asset_usage.py b/google/ads/googleads/v15/common/types/asset_usage.py new file mode 100644 index 000000000..444a670da --- /dev/null +++ b/google/ads/googleads/v15/common/types/asset_usage.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + served_asset_field_type as gage_served_asset_field_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/common/types/audiences.py b/google/ads/googleads/v15/common/types/audiences.py new file mode 100644 index 000000000..9c3635859 --- /dev/null +++ b/google/ads/googleads/v15/common/types/audiences.py @@ -0,0 +1,469 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import gender_type +from google.ads.googleads.v15.enums.types import income_range_type +from google.ads.googleads.v15.enums.types import parental_status_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.common.types.AgeDimension): + Dimension specifying users by their age. + + This field is a member of `oneof`_ ``dimension``. + gender (google.ads.googleads.v15.common.types.GenderDimension): + Dimension specifying users by their gender. + + This field is a member of `oneof`_ ``dimension``. + household_income (google.ads.googleads.v15.common.types.HouseholdIncomeDimension): + Dimension specifying users by their household + income. + + This field is a member of `oneof`_ ``dimension``. + parental_status (google.ads.googleads.v15.common.types.ParentalStatusDimension): + Dimension specifying users by their parental + status. + + This field is a member of `oneof`_ ``dimension``. + audience_segments (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.common.types.UserListSegment): + User list segment. + + This field is a member of `oneof`_ ``segment``. + user_interest (google.ads.googleads.v15.common.types.UserInterestSegment): + Affinity or In-market segment. + + This field is a member of `oneof`_ ``segment``. + life_event (google.ads.googleads.v15.common.types.LifeEventSegment): + Live-event audience segment. + + This field is a member of `oneof`_ ``segment``. + detailed_demographic (google.ads.googleads.v15.common.types.DetailedDemographicSegment): + Detailed demographic segment. + + This field is a member of `oneof`_ ``segment``. + custom_audience (google.ads.googleads.v15.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. + The Similar Audiences sunset starts May 2023. Refer to + https://ads-developers.googleblog.com/2022/11/announcing-deprecation-and-sunset-of.html + for other options. + + .. _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/v15/common/types/bidding.py b/google/ads/googleads/v15/common/types/bidding.py new file mode 100644 index 000000000..69f3e8b24 --- /dev/null +++ b/google/ads/googleads/v15/common/types/bidding.py @@ -0,0 +1,459 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import target_frequency_time_unit +from google.ads.googleads.v15.enums.types import ( + target_impression_share_location, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + manifest={ + "Commission", + "EnhancedCpc", + "ManualCpa", + "ManualCpc", + "ManualCpm", + "ManualCpv", + "MaximizeConversions", + "MaximizeConversionValue", + "TargetCpa", + "TargetCpm", + "TargetCpmTargetFrequencyGoal", + "TargetImpressionShare", + "TargetRoas", + "TargetSpend", + "PercentCpc", + }, +) + + +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. + + 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: 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, + ) + + +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.v15.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.v15.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.v15.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: 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, + ) + + +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): + 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/common/types/click_location.py b/google/ads/googleads/v15/common/types/click_location.py new file mode 100644 index 000000000..17da5c7b2 --- /dev/null +++ b/google/ads/googleads/v15/common/types/click_location.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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/v15/common/types/consent.py b/google/ads/googleads/v15/common/types/consent.py new file mode 100644 index 000000000..a58a10801 --- /dev/null +++ b/google/ads/googleads/v15/common/types/consent.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import consent_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + manifest={ + "Consent", + }, +) + + +class Consent(proto.Message): + r"""Consent + Attributes: + ad_user_data (google.ads.googleads.v15.enums.types.ConsentStatusEnum.ConsentStatus): + This represents consent for ad user data. + ad_personalization (google.ads.googleads.v15.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/v15/common/types/criteria.py b/google/ads/googleads/v15/common/types/criteria.py new file mode 100644 index 000000000..9deef4819 --- /dev/null +++ b/google/ads/googleads/v15/common/types/criteria.py @@ -0,0 +1,2035 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import age_range_type +from google.ads.googleads.v15.enums.types import app_payment_model_type +from google.ads.googleads.v15.enums.types import content_label_type +from google.ads.googleads.v15.enums.types import day_of_week as gage_day_of_week +from google.ads.googleads.v15.enums.types import device +from google.ads.googleads.v15.enums.types import gender_type +from google.ads.googleads.v15.enums.types import hotel_date_selection_type +from google.ads.googleads.v15.enums.types import income_range_type +from google.ads.googleads.v15.enums.types import interaction_type +from google.ads.googleads.v15.enums.types import keyword_match_type +from google.ads.googleads.v15.enums.types import listing_group_type +from google.ads.googleads.v15.enums.types import location_group_radius_units +from google.ads.googleads.v15.enums.types import minute_of_hour +from google.ads.googleads.v15.enums.types import parental_status_type +from google.ads.googleads.v15.enums.types import product_category_level +from google.ads.googleads.v15.enums.types import ( + product_channel as gage_product_channel, +) +from google.ads.googleads.v15.enums.types import ( + product_channel_exclusivity as gage_product_channel_exclusivity, +) +from google.ads.googleads.v15.enums.types import ( + product_condition as gage_product_condition, +) +from google.ads.googleads.v15.enums.types import product_custom_attribute_index +from google.ads.googleads.v15.enums.types import product_type_level +from google.ads.googleads.v15.enums.types import proximity_radius_units +from google.ads.googleads.v15.enums.types import webpage_condition_operand +from google.ads.googleads.v15.enums.types import webpage_condition_operator + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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", + "InteractionTypeInfo", + "AdScheduleInfo", + "AgeRangeInfo", + "GenderInfo", + "IncomeRangeInfo", + "ParentalStatusInfo", + "YouTubeVideoInfo", + "YouTubeChannelInfo", + "UserListInfo", + "ProximityInfo", + "GeoPointInfo", + "AddressInfo", + "TopicInfo", + "LanguageInfo", + "IpBlockInfo", + "ContentLabelInfo", + "CarrierInfo", + "UserInterestInfo", + "WebpageInfo", + "WebpageConditionInfo", + "WebpageSampleInfo", + "OperatingSystemVersionInfo", + "AppPaymentModelInfo", + "MobileDeviceInfo", + "CustomAffinityInfo", + "CustomIntentInfo", + "LocationGroupInfo", + "CustomAudienceInfo", + "CombinedAudienceInfo", + "AudienceInfo", + "KeywordThemeInfo", + "LocalServiceIdInfo", + "SearchThemeInfo", + "BrandInfo", + "BrandListInfo", + }, +) + + +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.v15.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.v15.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.v15.enums.types.ListingGroupTypeEnum.ListingGroupType): + Type of the listing group. + case_value (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.common.types.HotelIdInfo): + Advertiser-specific hotel ID. + + This field is a member of `oneof`_ ``dimension``. + hotel_class (google.ads.googleads.v15.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.v15.common.types.HotelCountryRegionInfo): + Country or Region the hotel is located in. + + This field is a member of `oneof`_ ``dimension``. + hotel_state (google.ads.googleads.v15.common.types.HotelStateInfo): + State the hotel is located in. + + This field is a member of `oneof`_ ``dimension``. + hotel_city (google.ads.googleads.v15.common.types.HotelCityInfo): + City the hotel is located in. + + This field is a member of `oneof`_ ``dimension``. + product_category (google.ads.googleads.v15.common.types.ProductCategoryInfo): + Category of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_brand (google.ads.googleads.v15.common.types.ProductBrandInfo): + Brand of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_channel (google.ads.googleads.v15.common.types.ProductChannelInfo): + Locality of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_channel_exclusivity (google.ads.googleads.v15.common.types.ProductChannelExclusivityInfo): + Availability of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_condition (google.ads.googleads.v15.common.types.ProductConditionInfo): + Condition of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_custom_attribute (google.ads.googleads.v15.common.types.ProductCustomAttributeInfo): + Custom attribute of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_item_id (google.ads.googleads.v15.common.types.ProductItemIdInfo): + Item id of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_type (google.ads.googleads.v15.common.types.ProductTypeInfo): + Type of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_grouping (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.common.types.ActivityIdInfo): + Advertiser-specific activity ID. + + This field is a member of `oneof`_ ``dimension``. + activity_rating (google.ads.googleads.v15.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.v15.common.types.ActivityCountryInfo): + Country the activity is in. + + This field is a member of `oneof`_ ``dimension``. + unknown_listing_dimension (google.ads.googleads.v15.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", + ) + 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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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"""Country the activity is in. + .. _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 InteractionTypeInfo(proto.Message): + r"""Criterion for Interaction Type. + Attributes: + type_ (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.enums.types.ProximityRadiusUnitsEnum.ProximityRadiusUnits): + The unit of measurement of the radius. + Default is KILOMETERS. + address (google.ads.googleads.v15.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 IP exclusions. We allow: + + - IPv4 and IPv6 addresses + - individual addresses (192.168.0.1) + - masks for individual addresses (192.168.0.1/32) + - masks for Class C networks (192.168.0.1/24) + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + ip_address (str): + The IP address of this IP block. + + 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.v15.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.v15.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.v15.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.v15.enums.types.WebpageConditionOperandEnum.WebpageConditionOperand): + Operand of webpage targeting condition. + operator (google.ads.googleads.v15.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 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.v15.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: + feed (str): + Feed specifying locations for targeting. + Cannot be set with AssetSet fields. This is + required and must be set in CREATE operations. + + This field is a member of `oneof`_ ``_feed``. + 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.v15.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. + """ + + feed: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + 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: + entity_id (str): + The Commercial KG MID for the brand. + + This field is a member of `oneof`_ ``_entity_id``. + """ + + entity_id: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + + +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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/common/types/criterion_category_availability.py b/google/ads/googleads/v15/common/types/criterion_category_availability.py new file mode 100644 index 000000000..2c2906663 --- /dev/null +++ b/google/ads/googleads/v15/common/types/criterion_category_availability.py @@ -0,0 +1,168 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + advertising_channel_sub_type as gage_advertising_channel_sub_type, +) +from google.ads.googleads.v15.enums.types import ( + advertising_channel_type as gage_advertising_channel_type, +) +from google.ads.googleads.v15.enums.types import ( + criterion_category_channel_availability_mode, +) +from google.ads.googleads.v15.enums.types import ( + criterion_category_locale_availability_mode, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + manifest={ + "CriterionCategoryAvailability", + "CriterionCategoryChannelAvailability", + "CriterionCategoryLocaleAvailability", + }, +) + + +class CriterionCategoryAvailability(proto.Message): + r"""Information of category availability, per advertising + channel. + + Attributes: + channel (google.ads.googleads.v15.common.types.CriterionCategoryChannelAvailability): + Channel types and subtypes that are available + to the category. + locale (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.enums.types.AdvertisingChannelTypeEnum.AdvertisingChannelType): + Channel type the category is available to. + advertising_channel_sub_type (MutableSequence[google.ads.googleads.v15.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.v15.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/v15/common/types/custom_parameter.py b/google/ads/googleads/v15/common/types/custom_parameter.py new file mode 100644 index 000000000..29d858367 --- /dev/null +++ b/google/ads/googleads/v15/common/types/custom_parameter.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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/v15/common/types/customizer_value.py b/google/ads/googleads/v15/common/types/customizer_value.py new file mode 100644 index 000000000..6be7ba2f4 --- /dev/null +++ b/google/ads/googleads/v15/common/types/customizer_value.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import customizer_attribute_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/common/types/dates.py b/google/ads/googleads/v15/common/types/dates.py new file mode 100644 index 000000000..c362e7e36 --- /dev/null +++ b/google/ads/googleads/v15/common/types/dates.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import month_of_year + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.common.types.YearMonth): + The inclusive start year month. + end (google.ads.googleads.v15.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.v15.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/v15/common/types/extensions.py b/google/ads/googleads/v15/common/types/extensions.py new file mode 100644 index 000000000..428bf62d7 --- /dev/null +++ b/google/ads/googleads/v15/common/types/extensions.py @@ -0,0 +1,911 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import custom_parameter +from google.ads.googleads.v15.common.types import feed_common +from google.ads.googleads.v15.enums.types import app_store as gage_app_store +from google.ads.googleads.v15.enums.types import ( + call_conversion_reporting_state as gage_call_conversion_reporting_state, +) +from google.ads.googleads.v15.enums.types import price_extension_price_qualifier +from google.ads.googleads.v15.enums.types import price_extension_price_unit +from google.ads.googleads.v15.enums.types import price_extension_type +from google.ads.googleads.v15.enums.types import ( + promotion_extension_discount_modifier, +) +from google.ads.googleads.v15.enums.types import promotion_extension_occasion + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + manifest={ + "AppFeedItem", + "CallFeedItem", + "CalloutFeedItem", + "LocationFeedItem", + "AffiliateLocationFeedItem", + "TextMessageFeedItem", + "PriceFeedItem", + "PriceOffer", + "PromotionFeedItem", + "StructuredSnippetFeedItem", + "SitelinkFeedItem", + "HotelCalloutFeedItem", + "ImageFeedItem", + }, +) + + +class AppFeedItem(proto.Message): + r"""Represents an App extension. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + link_text (str): + The visible text displayed when the link is + rendered in an ad. This string must not be + empty, and the length of this string should be + between 1 and 25, inclusive. + + This field is a member of `oneof`_ ``_link_text``. + app_id (str): + The store-specific ID for the target + application. This string must not be empty. + + This field is a member of `oneof`_ ``_app_id``. + app_store (google.ads.googleads.v15.enums.types.AppStoreEnum.AppStore): + The application store that the target + application belongs to. This field is required. + final_urls (MutableSequence[str]): + A list of possible final URLs after all cross + domain redirects. This list must not be empty. + 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. + Default value is "{lpurl}". + + This field is a member of `oneof`_ ``_tracking_url_template``. + url_custom_parameters (MutableSequence[google.ads.googleads.v15.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``. + """ + + link_text: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + app_id: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + app_store: gage_app_store.AppStoreEnum.AppStore = proto.Field( + proto.ENUM, + number=3, + enum=gage_app_store.AppStoreEnum.AppStore, + ) + final_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=11, + ) + final_mobile_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=12, + ) + tracking_url_template: str = proto.Field( + proto.STRING, + number=13, + 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=14, + optional=True, + ) + + +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.v15.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 LocationFeedItem(proto.Message): + r"""Represents a location extension. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + business_name (str): + The name of the business. + + This field is a member of `oneof`_ ``_business_name``. + address_line_1 (str): + Line 1 of the business address. + + This field is a member of `oneof`_ ``_address_line_1``. + address_line_2 (str): + Line 2 of the business address. + + This field is a member of `oneof`_ ``_address_line_2``. + city (str): + City of the business address. + + This field is a member of `oneof`_ ``_city``. + province (str): + Province of the business address. + + This field is a member of `oneof`_ ``_province``. + postal_code (str): + Postal code of the business address. + + This field is a member of `oneof`_ ``_postal_code``. + country_code (str): + Country code of the business address. + + This field is a member of `oneof`_ ``_country_code``. + phone_number (str): + Phone number of the business. + + This field is a member of `oneof`_ ``_phone_number``. + """ + + business_name: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + address_line_1: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + address_line_2: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + city: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + province: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + postal_code: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=15, + optional=True, + ) + phone_number: str = proto.Field( + proto.STRING, + number=16, + optional=True, + ) + + +class AffiliateLocationFeedItem(proto.Message): + r"""Represents an affiliate location extension. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + business_name (str): + The name of the business. + + This field is a member of `oneof`_ ``_business_name``. + address_line_1 (str): + Line 1 of the business address. + + This field is a member of `oneof`_ ``_address_line_1``. + address_line_2 (str): + Line 2 of the business address. + + This field is a member of `oneof`_ ``_address_line_2``. + city (str): + City of the business address. + + This field is a member of `oneof`_ ``_city``. + province (str): + Province of the business address. + + This field is a member of `oneof`_ ``_province``. + postal_code (str): + Postal code of the business address. + + This field is a member of `oneof`_ ``_postal_code``. + country_code (str): + Country code of the business address. + + This field is a member of `oneof`_ ``_country_code``. + phone_number (str): + Phone number of the business. + + This field is a member of `oneof`_ ``_phone_number``. + chain_id (int): + Id of the retail chain that is advertised as + a seller of your product. + + This field is a member of `oneof`_ ``_chain_id``. + chain_name (str): + Name of chain. + + This field is a member of `oneof`_ ``_chain_name``. + """ + + business_name: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + address_line_1: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + address_line_2: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + city: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + province: str = proto.Field( + proto.STRING, + number=15, + optional=True, + ) + postal_code: str = proto.Field( + proto.STRING, + number=16, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=17, + optional=True, + ) + phone_number: str = proto.Field( + proto.STRING, + number=18, + optional=True, + ) + chain_id: int = proto.Field( + proto.INT64, + number=19, + optional=True, + ) + chain_name: str = proto.Field( + proto.STRING, + number=20, + optional=True, + ) + + +class TextMessageFeedItem(proto.Message): + r"""An extension that users can click on to send a text message + to the advertiser. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + business_name (str): + The business name to prepend to the message + text. This field is required. + + This field is a member of `oneof`_ ``_business_name``. + country_code (str): + Uppercase two-letter country code of the + advertiser's phone number. This field is + required. + + This field is a member of `oneof`_ ``_country_code``. + phone_number (str): + The advertiser's phone number the message + will be sent to. Required. + + This field is a member of `oneof`_ ``_phone_number``. + text (str): + The text to show in the ad. + This field is required. + + This field is a member of `oneof`_ ``_text``. + extension_text (str): + The message extension_text populated in the messaging app. + + This field is a member of `oneof`_ ``_extension_text``. + """ + + business_name: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + country_code: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + phone_number: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + text: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + extension_text: str = proto.Field( + proto.STRING, + number=10, + optional=True, + ) + + +class PriceFeedItem(proto.Message): + r"""Represents a Price extension. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + type_ (google.ads.googleads.v15.enums.types.PriceExtensionTypeEnum.PriceExtensionType): + Price extension type of this extension. + price_qualifier (google.ads.googleads.v15.enums.types.PriceExtensionPriceQualifierEnum.PriceExtensionPriceQualifier): + Price qualifier for all offers of this price + extension. + tracking_url_template (str): + Tracking URL template for all offers of this + price extension. + + This field is a member of `oneof`_ ``_tracking_url_template``. + language_code (str): + The code of the language used for this price + extension. + + This field is a member of `oneof`_ ``_language_code``. + price_offerings (MutableSequence[google.ads.googleads.v15.common.types.PriceOffer]): + The price offerings in this price extension. + final_url_suffix (str): + Tracking URL template for all offers of this + price extension. + + This field is a member of `oneof`_ ``_final_url_suffix``. + """ + + 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, + ) + tracking_url_template: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + language_code: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + price_offerings: MutableSequence["PriceOffer"] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="PriceOffer", + ) + final_url_suffix: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + + +class PriceOffer(proto.Message): + r"""Represents one price offer in a price extension. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + header (str): + Header text of this offer. + + This field is a member of `oneof`_ ``_header``. + description (str): + Description text of this offer. + + This field is a member of `oneof`_ ``_description``. + price (google.ads.googleads.v15.common.types.Money): + Price value of this offer. + unit (google.ads.googleads.v15.enums.types.PriceExtensionPriceUnitEnum.PriceExtensionPriceUnit): + Price unit for this offer. + 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. + """ + + header: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + description: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + 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_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=9, + ) + final_mobile_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=10, + ) + + +class PromotionFeedItem(proto.Message): + r"""Represents a Promotion extension. + 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): + A freeform description of what the promotion + is targeting. This field is required. + + This field is a member of `oneof`_ ``_promotion_target``. + discount_modifier (google.ads.googleads.v15.enums.types.PromotionExtensionDiscountModifierEnum.PromotionExtensionDiscountModifier): + Enum that modifies the qualification of the + discount. + promotion_start_date (str): + Start date of when the promotion is eligible + to be redeemed. + + This field is a member of `oneof`_ ``_promotion_start_date``. + promotion_end_date (str): + Last date when the promotion is eligible to + be redeemed. + + This field is a member of `oneof`_ ``_promotion_end_date``. + occasion (google.ads.googleads.v15.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. + final_urls (MutableSequence[str]): + A list of possible final URLs after all cross + domain redirects. This field is required. + 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.v15.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``. + language_code (str): + The language of the promotion. + Represented as BCP 47 language tag. + + This field is a member of `oneof`_ ``_language_code``. + percent_off (int): + Percentage off discount in the promotion in micros. One + million is equivalent to one percent. Either this or + money_off_amount is required. + + This field is a member of `oneof`_ ``discount_type``. + money_amount_off (google.ads.googleads.v15.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.v15.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_target: str = proto.Field( + proto.STRING, + number=16, + optional=True, + ) + discount_modifier: promotion_extension_discount_modifier.PromotionExtensionDiscountModifierEnum.PromotionExtensionDiscountModifier = proto.Field( + proto.ENUM, + number=2, + enum=promotion_extension_discount_modifier.PromotionExtensionDiscountModifierEnum.PromotionExtensionDiscountModifier, + ) + promotion_start_date: str = proto.Field( + proto.STRING, + number=19, + optional=True, + ) + promotion_end_date: str = proto.Field( + proto.STRING, + number=20, + optional=True, + ) + occasion: promotion_extension_occasion.PromotionExtensionOccasionEnum.PromotionExtensionOccasion = proto.Field( + proto.ENUM, + number=9, + enum=promotion_extension_occasion.PromotionExtensionOccasionEnum.PromotionExtensionOccasion, + ) + final_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=21, + ) + final_mobile_urls: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=22, + ) + tracking_url_template: str = proto.Field( + proto.STRING, + number=23, + optional=True, + ) + url_custom_parameters: MutableSequence[ + custom_parameter.CustomParameter + ] = proto.RepeatedField( + proto.MESSAGE, + number=13, + message=custom_parameter.CustomParameter, + ) + final_url_suffix: str = proto.Field( + proto.STRING, + number=24, + optional=True, + ) + language_code: str = proto.Field( + proto.STRING, + number=25, + optional=True, + ) + percent_off: int = proto.Field( + proto.INT64, + number=17, + 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=18, + oneof="promotion_trigger", + ) + orders_over_amount: feed_common.Money = proto.Field( + proto.MESSAGE, + number=6, + oneof="promotion_trigger", + message=feed_common.Money, + ) + + +class StructuredSnippetFeedItem(proto.Message): + r"""Represents a structured snippet extension. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + header (str): + The header of the snippet. + This string must not be empty. + + This field is a member of `oneof`_ ``_header``. + values (MutableSequence[str]): + The values in the snippet. + The maximum size of this collection is 10. + """ + + header: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + values: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=4, + ) + + +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.v15.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, + ) + + +class HotelCalloutFeedItem(proto.Message): + r"""Represents a hotel callout extension. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + text (str): + The callout text. + The length of this string should be between 1 + and 25, inclusive. + + This field is a member of `oneof`_ ``_text``. + language_code (str): + The language of the hotel callout text. + IETF BCP 47 compliant language code. + + This field is a member of `oneof`_ ``_language_code``. + """ + + text: str = proto.Field( + proto.STRING, + number=3, + optional=True, + ) + language_code: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + + +class ImageFeedItem(proto.Message): + r"""Represents an advertiser provided image extension. + Attributes: + image_asset (str): + Required. Resource name of the image asset. + """ + + image_asset: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/common/types/feed_common.py b/google/ads/googleads/v15/common/types/feed_common.py new file mode 100644 index 000000000..c372a8f68 --- /dev/null +++ b/google/ads/googleads/v15/common/types/feed_common.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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/v15/common/types/feed_item_set_filter_type_infos.py b/google/ads/googleads/v15/common/types/feed_item_set_filter_type_infos.py new file mode 100644 index 000000000..460fd02d8 --- /dev/null +++ b/google/ads/googleads/v15/common/types/feed_item_set_filter_type_infos.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + feed_item_set_string_filter_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + manifest={ + "DynamicLocationSetFilter", + "BusinessNameFilter", + "DynamicAffiliateLocationSetFilter", + }, +) + + +class DynamicLocationSetFilter(proto.Message): + r"""Represents a filter on locations in a feed item set. + Only applicable if the parent Feed of the FeedItemSet is a + LOCATION feed. + + Attributes: + labels (MutableSequence[str]): + If multiple labels are set, then only + feeditems marked with all the labels will be + added to the FeedItemSet. + business_name_filter (google.ads.googleads.v15.common.types.BusinessNameFilter): + Business name filter. + """ + + labels: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + business_name_filter: "BusinessNameFilter" = proto.Field( + proto.MESSAGE, + number=2, + message="BusinessNameFilter", + ) + + +class BusinessNameFilter(proto.Message): + r"""Represents a business name filter on locations in a + FeedItemSet. + + Attributes: + business_name (str): + Business name string to use for filtering. + filter_type (google.ads.googleads.v15.enums.types.FeedItemSetStringFilterTypeEnum.FeedItemSetStringFilterType): + The type of string matching to use when filtering with + business_name. + """ + + business_name: str = proto.Field( + proto.STRING, + number=1, + ) + filter_type: feed_item_set_string_filter_type.FeedItemSetStringFilterTypeEnum.FeedItemSetStringFilterType = proto.Field( + proto.ENUM, + number=2, + enum=feed_item_set_string_filter_type.FeedItemSetStringFilterTypeEnum.FeedItemSetStringFilterType, + ) + + +class DynamicAffiliateLocationSetFilter(proto.Message): + r"""Represents a filter on affiliate locations in a FeedItemSet. Only + applicable if the parent Feed of the FeedItemSet is an + AFFILIATE_LOCATION feed. + + Attributes: + chain_ids (MutableSequence[int]): + Used to filter affiliate locations by chain + ids. Only affiliate locations that belong to the + specified chain(s) will be added to the + FeedItemSet. + """ + + chain_ids: MutableSequence[int] = proto.RepeatedField( + proto.INT64, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/common/types/final_app_url.py b/google/ads/googleads/v15/common/types/final_app_url.py new file mode 100644 index 000000000..824acd5ad --- /dev/null +++ b/google/ads/googleads/v15/common/types/final_app_url.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import app_url_operating_system_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/common/types/frequency_cap.py b/google/ads/googleads/v15/common/types/frequency_cap.py new file mode 100644 index 000000000..9e3d6e18d --- /dev/null +++ b/google/ads/googleads/v15/common/types/frequency_cap.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import frequency_cap_event_type +from google.ads.googleads.v15.enums.types import frequency_cap_level +from google.ads.googleads.v15.enums.types import frequency_cap_time_unit + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.enums.types.FrequencyCapEventTypeEnum.FrequencyCapEventType): + The type of event that the cap applies to + (for example, impression). + time_unit (google.ads.googleads.v15.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/v15/common/types/keyword_plan_common.py b/google/ads/googleads/v15/common/types/keyword_plan_common.py new file mode 100644 index 000000000..119c8ab61 --- /dev/null +++ b/google/ads/googleads/v15/common/types/keyword_plan_common.py @@ -0,0 +1,324 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import dates +from google.ads.googleads.v15.enums.types import device as gage_device +from google.ads.googleads.v15.enums.types import ( + keyword_plan_aggregate_metric_type, +) +from google.ads.googleads.v15.enums.types import keyword_plan_competition_level +from google.ads.googleads.v15.enums.types import keyword_plan_concept_group_type +from google.ads.googleads.v15.enums.types import month_of_year + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.common.types.MonthlySearchVolume]): + Approximate number of searches on this query + for the past twelve months. + competition (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/common/types/lifecycle_goals.py b/google/ads/googleads/v15/common/types/lifecycle_goals.py new file mode 100644 index 000000000..d70c21c27 --- /dev/null +++ b/google/ads/googleads/v15/common/types/lifecycle_goals.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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. + In current stage, high lifetime value feature is + in beta and this field is read-only. + + 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/v15/common/types/local_services.py b/google/ads/googleads/v15/common/types/local_services.py new file mode 100644 index 000000000..587deeb6b --- /dev/null +++ b/google/ads/googleads/v15/common/types/local_services.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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/v15/common/types/matching_function.py b/google/ads/googleads/v15/common/types/matching_function.py new file mode 100644 index 000000000..42b159fb9 --- /dev/null +++ b/google/ads/googleads/v15/common/types/matching_function.py @@ -0,0 +1,269 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import matching_function_context_type +from google.ads.googleads.v15.enums.types import matching_function_operator + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + manifest={ + "MatchingFunction", + "Operand", + }, +) + + +class MatchingFunction(proto.Message): + r"""Matching function associated with a + CustomerFeed, CampaignFeed, or AdGroupFeed. The matching + function is used to filter the set of feed items selected. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + function_string (str): + String representation of the Function. + + Examples: + + 1. IDENTITY(true) or IDENTITY(false). All or no feed items + served. + 2. EQUALS(CONTEXT.DEVICE,"Mobile") + 3. IN(FEED_ITEM_ID,{1000001,1000002,1000003}) + 4. CONTAINS_ANY(FeedAttribute[12345678,0],{"Mars + cruise","Venus cruise"}) + 5. AND(IN(FEED_ITEM_ID,{10001,10002}),EQUALS(CONTEXT.DEVICE,"Mobile")) + + For more details, visit + https://developers.google.com/google-ads/api/docs/extensions/feeds/matching-functions + + Note that because multiple strings may represent the same + underlying function (whitespace and single versus double + quotation marks, for example), the value returned may not be + identical to the string sent in a mutate request. + + This field is a member of `oneof`_ ``_function_string``. + operator (google.ads.googleads.v15.enums.types.MatchingFunctionOperatorEnum.MatchingFunctionOperator): + Operator for a function. + left_operands (MutableSequence[google.ads.googleads.v15.common.types.Operand]): + The operands on the left hand side of the + equation. This is also the operand to be used + for single operand expressions such as NOT. + right_operands (MutableSequence[google.ads.googleads.v15.common.types.Operand]): + The operands on the right hand side of the + equation. + """ + + function_string: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + operator: matching_function_operator.MatchingFunctionOperatorEnum.MatchingFunctionOperator = proto.Field( + proto.ENUM, + number=4, + enum=matching_function_operator.MatchingFunctionOperatorEnum.MatchingFunctionOperator, + ) + left_operands: MutableSequence["Operand"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="Operand", + ) + right_operands: MutableSequence["Operand"] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="Operand", + ) + + +class Operand(proto.Message): + r"""An operand in a matching function. + 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: + constant_operand (google.ads.googleads.v15.common.types.Operand.ConstantOperand): + A constant operand in a matching function. + + This field is a member of `oneof`_ ``function_argument_operand``. + feed_attribute_operand (google.ads.googleads.v15.common.types.Operand.FeedAttributeOperand): + This operand specifies a feed attribute in + feed. + + This field is a member of `oneof`_ ``function_argument_operand``. + function_operand (google.ads.googleads.v15.common.types.Operand.FunctionOperand): + A function operand in a matching function. + Used to represent nested functions. + + This field is a member of `oneof`_ ``function_argument_operand``. + request_context_operand (google.ads.googleads.v15.common.types.Operand.RequestContextOperand): + An operand in a function referring to a value + in the request context. + + This field is a member of `oneof`_ ``function_argument_operand``. + """ + + class ConstantOperand(proto.Message): + r"""A constant operand in a matching function. + 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: + string_value (str): + String value of the operand if it is a string + type. + + This field is a member of `oneof`_ ``constant_operand_value``. + long_value (int): + Int64 value of the operand if it is a int64 + type. + + This field is a member of `oneof`_ ``constant_operand_value``. + boolean_value (bool): + Boolean value of the operand if it is a + boolean type. + + This field is a member of `oneof`_ ``constant_operand_value``. + double_value (float): + Double value of the operand if it is a double + type. + + This field is a member of `oneof`_ ``constant_operand_value``. + """ + + string_value: str = proto.Field( + proto.STRING, + number=5, + oneof="constant_operand_value", + ) + long_value: int = proto.Field( + proto.INT64, + number=6, + oneof="constant_operand_value", + ) + boolean_value: bool = proto.Field( + proto.BOOL, + number=7, + oneof="constant_operand_value", + ) + double_value: float = proto.Field( + proto.DOUBLE, + number=8, + oneof="constant_operand_value", + ) + + class FeedAttributeOperand(proto.Message): + r"""A feed attribute operand in a matching function. + Used to represent a feed attribute in feed. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + feed_id (int): + The associated feed. Required. + + This field is a member of `oneof`_ ``_feed_id``. + feed_attribute_id (int): + Id of the referenced feed attribute. + Required. + + This field is a member of `oneof`_ ``_feed_attribute_id``. + """ + + feed_id: int = proto.Field( + proto.INT64, + number=3, + optional=True, + ) + feed_attribute_id: int = proto.Field( + proto.INT64, + number=4, + optional=True, + ) + + class FunctionOperand(proto.Message): + r"""A function operand in a matching function. + Used to represent nested functions. + + Attributes: + matching_function (google.ads.googleads.v15.common.types.MatchingFunction): + The matching function held in this operand. + """ + + matching_function: "MatchingFunction" = proto.Field( + proto.MESSAGE, + number=1, + message="MatchingFunction", + ) + + class RequestContextOperand(proto.Message): + r"""An operand in a function referring to a value in the request + context. + + Attributes: + context_type (google.ads.googleads.v15.enums.types.MatchingFunctionContextTypeEnum.MatchingFunctionContextType): + Type of value to be referred in the request + context. + """ + + context_type: matching_function_context_type.MatchingFunctionContextTypeEnum.MatchingFunctionContextType = proto.Field( + proto.ENUM, + number=1, + enum=matching_function_context_type.MatchingFunctionContextTypeEnum.MatchingFunctionContextType, + ) + + constant_operand: ConstantOperand = proto.Field( + proto.MESSAGE, + number=1, + oneof="function_argument_operand", + message=ConstantOperand, + ) + feed_attribute_operand: FeedAttributeOperand = proto.Field( + proto.MESSAGE, + number=2, + oneof="function_argument_operand", + message=FeedAttributeOperand, + ) + function_operand: FunctionOperand = proto.Field( + proto.MESSAGE, + number=3, + oneof="function_argument_operand", + message=FunctionOperand, + ) + request_context_operand: RequestContextOperand = proto.Field( + proto.MESSAGE, + number=4, + oneof="function_argument_operand", + message=RequestContextOperand, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/common/types/metric_goal.py b/google/ads/googleads/v15/common/types/metric_goal.py new file mode 100644 index 000000000..3bcff7dff --- /dev/null +++ b/google/ads/googleads/v15/common/types/metric_goal.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import experiment_metric +from google.ads.googleads.v15.enums.types import experiment_metric_direction + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + manifest={ + "MetricGoal", + }, +) + + +class MetricGoal(proto.Message): + r"""A metric goal for an experiment. + Attributes: + metric (google.ads.googleads.v15.enums.types.ExperimentMetricEnum.ExperimentMetric): + The metric of the goal. For example, clicks, + impressions, cost, conversions, etc. + direction (google.ads.googleads.v15.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/v15/common/types/metrics.py b/google/ads/googleads/v15/common/types/metrics.py new file mode 100644 index 000000000..13824d6a4 --- /dev/null +++ b/google/ads/googleads/v15/common/types/metrics.py @@ -0,0 +1,2353 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import interaction_event_type +from google.ads.googleads.v15.enums.types import quality_score_bucket + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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): + The percent of your ad impressions that are + shown as the very first ad above the organic + search results. + + 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. + 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. + 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 store 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 store 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 store'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 store 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 + store) 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 + store 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 store'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 as the very first ad above + the 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_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 above the 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``. + 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 views. + + This field is a member of `oneof`_ ``_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``. + 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. + 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. + 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_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``. + 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.v15.enums.types.QualityScoreBucketEnum.QualityScoreBucket): + The creative historical quality score. + historical_landing_page_quality_score (google.ads.googleads.v15.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.v15.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 store'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.v15.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``. + 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 above the organic + 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 anywhere above the 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 above the organic + 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 anywhere above the 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 in the top + location (anywhere above the organic search + results) compared to the estimated number of + impressions you were eligible to receive in the + top location. 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. + + This field is a member of `oneof`_ ``_search_top_impression_share``. + search_volume (google.ads.googleads.v15.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 anywhere above the 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_view_rate (float): + The number of views your TrueView 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_view_rate``. + video_views (int): + The number of times your video ads were + viewed. + + This field is a member of `oneof`_ ``_video_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 store 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 store + 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 store 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``. + """ + + 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, + ) + 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, + ) + 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, + ) + average_cpv: float = proto.Field( + proto.DOUBLE, + number=207, + 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, + ) + 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, + ) + 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, + ) + 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_value_micros: int = proto.Field( + proto.INT64, + number=312, + 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, + ) + 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_view_rate: float = proto.Field( + proto.DOUBLE, + number=153, + optional=True, + ) + video_views: int = proto.Field( + proto.INT64, + number=154, + 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, + ) + + +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/v15/common/types/offline_user_data.py b/google/ads/googleads/v15/common/types/offline_user_data.py new file mode 100644 index 000000000..53e47c66c --- /dev/null +++ b/google/ads/googleads/v15/common/types/offline_user_data.py @@ -0,0 +1,776 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import consent as gagc_consent +from google.ads.googleads.v15.enums.types import ( + user_identifier_source as gage_user_identifier_source, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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. + Accessible only to customers on the allow-list. + + This field is a member of `oneof`_ ``_order_id``. + store_attribute (google.ads.googleads.v15.common.types.StoreAttribute): + Store attributes of the transaction. + Accessible only to customers on the allow-list. + custom_value (str): + Value of the custom variable for each + transaction. Accessible only to customers on the + allow-list. + + This field is a member of `oneof`_ ``_custom_value``. + item_attribute (google.ads.googleads.v15.common.types.ItemAttribute): + Item attributes of the transaction. + """ + + 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 can be + either the Merchant Center Item ID or GTIN + (Global Trade Item Number). + merchant_id (int): + ID of the Merchant Center Account. + + 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. + language_code (str): + ISO 639-1 code of the language associated + with the feed where your items are uploaded + 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.v15.common.types.UserIdentifier]): + User identification info. Required. + transaction_attribute (google.ads.googleads.v15.common.types.TransactionAttribute): + Additional transactions/attributes associated + with the user. Required when updating store + sales data. + user_attribute (google.ads.googleads.v15.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.v15.common.types.Consent): + The consent setting for the user. Customer + match will ignore this field and return a + warning. + + 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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/common/types/policy.py b/google/ads/googleads/v15/common/types/policy.py new file mode 100644 index 000000000..6d7ca043f --- /dev/null +++ b/google/ads/googleads/v15/common/types/policy.py @@ -0,0 +1,496 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import policy_topic_entry_type +from google.ads.googleads.v15.enums.types import ( + policy_topic_evidence_destination_mismatch_url_type, +) +from google.ads.googleads.v15.enums.types import ( + policy_topic_evidence_destination_not_working_device, +) +from google.ads.googleads.v15.enums.types import ( + policy_topic_evidence_destination_not_working_dns_error_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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 currently only compatible with Enhanced + Text Ad. It corresponds to the + PolicyTopicEntry.topic field. + + Resources violating 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.v15.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. + """ + + 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.v15.enums.types.PolicyTopicEntryTypeEnum.PolicyTopicEntryType): + Describes the negative or positive effect + this policy will have on serving. + evidences (MutableSequence[google.ads.googleads.v15.common.types.PolicyTopicEvidence]): + Additional information that explains policy + finding (for example, the brand name for a + trademark finding). + constraints (MutableSequence[google.ads.googleads.v15.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.v15.common.types.PolicyTopicEvidence.WebsiteList): + List of websites linked with this resource. + + This field is a member of `oneof`_ ``value``. + text_list (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.common.types.PolicyTopicConstraint.CountryConstraintList): + Countries where the resource cannot serve. + + This field is a member of `oneof`_ ``value``. + reseller_constraint (google.ads.googleads.v15.common.types.PolicyTopicConstraint.ResellerConstraint): + Reseller constraint. + + This field is a member of `oneof`_ ``value``. + certificate_missing_in_country_list (google.ads.googleads.v15.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.v15.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.v15.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/v15/common/types/policy_summary.py b/google/ads/googleads/v15/common/types/policy_summary.py new file mode 100644 index 000000000..2a7b587e0 --- /dev/null +++ b/google/ads/googleads/v15/common/types/policy_summary.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import policy +from google.ads.googleads.v15.enums.types import policy_approval_status +from google.ads.googleads.v15.enums.types import policy_review_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + manifest={ + "PolicySummary", + }, +) + + +class PolicySummary(proto.Message): + r"""Contains policy summary information. + Attributes: + policy_topic_entries (MutableSequence[google.ads.googleads.v15.common.types.PolicyTopicEntry]): + The list of policy findings. + review_status (google.ads.googleads.v15.enums.types.PolicyReviewStatusEnum.PolicyReviewStatus): + Where in the review process the resource is. + approval_status (google.ads.googleads.v15.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/v15/common/types/real_time_bidding_setting.py b/google/ads/googleads/v15/common/types/real_time_bidding_setting.py new file mode 100644 index 000000000..747619dfe --- /dev/null +++ b/google/ads/googleads/v15/common/types/real_time_bidding_setting.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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/v15/common/types/segments.py b/google/ads/googleads/v15/common/types/segments.py new file mode 100644 index 000000000..371604c3f --- /dev/null +++ b/google/ads/googleads/v15/common/types/segments.py @@ -0,0 +1,1171 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import criteria +from google.ads.googleads.v15.enums.types import ( + ad_destination_type as gage_ad_destination_type, +) +from google.ads.googleads.v15.enums.types import ( + ad_network_type as gage_ad_network_type, +) +from google.ads.googleads.v15.enums.types import ( + budget_campaign_association_status as gage_budget_campaign_association_status, +) +from google.ads.googleads.v15.enums.types import click_type as gage_click_type +from google.ads.googleads.v15.enums.types import ( + conversion_action_category as gage_conversion_action_category, +) +from google.ads.googleads.v15.enums.types import ( + conversion_attribution_event_type as gage_conversion_attribution_event_type, +) +from google.ads.googleads.v15.enums.types import ( + conversion_lag_bucket as gage_conversion_lag_bucket, +) +from google.ads.googleads.v15.enums.types import ( + conversion_or_adjustment_lag_bucket as gage_conversion_or_adjustment_lag_bucket, +) +from google.ads.googleads.v15.enums.types import ( + conversion_value_rule_primary_dimension as gage_conversion_value_rule_primary_dimension, +) +from google.ads.googleads.v15.enums.types import ( + converting_user_prior_engagement_type_and_ltv_bucket, +) +from google.ads.googleads.v15.enums.types import day_of_week as gage_day_of_week +from google.ads.googleads.v15.enums.types import device as gage_device +from google.ads.googleads.v15.enums.types import ( + external_conversion_source as gage_external_conversion_source, +) +from google.ads.googleads.v15.enums.types import ( + hotel_date_selection_type as gage_hotel_date_selection_type, +) +from google.ads.googleads.v15.enums.types import ( + hotel_price_bucket as gage_hotel_price_bucket, +) +from google.ads.googleads.v15.enums.types import ( + hotel_rate_type as gage_hotel_rate_type, +) +from google.ads.googleads.v15.enums.types import ( + month_of_year as gage_month_of_year, +) +from google.ads.googleads.v15.enums.types import ( + placeholder_type as gage_placeholder_type, +) +from google.ads.googleads.v15.enums.types import ( + product_channel as gage_product_channel, +) +from google.ads.googleads.v15.enums.types import ( + product_channel_exclusivity as gage_product_channel_exclusivity, +) +from google.ads.googleads.v15.enums.types import ( + product_condition as gage_product_condition, +) +from google.ads.googleads.v15.enums.types import ( + recommendation_type as gage_recommendation_type, +) +from google.ads.googleads.v15.enums.types import ( + search_engine_results_page_type as gage_search_engine_results_page_type, +) +from google.ads.googleads.v15.enums.types import ( + search_term_match_type as gage_search_term_match_type, +) +from google.ads.googleads.v15.enums.types import ( + sk_ad_network_ad_event_type as gage_sk_ad_network_ad_event_type, +) +from google.ads.googleads.v15.enums.types import ( + sk_ad_network_attribution_credit as gage_sk_ad_network_attribution_credit, +) +from google.ads.googleads.v15.enums.types import ( + sk_ad_network_coarse_conversion_value as gage_sk_ad_network_coarse_conversion_value, +) +from google.ads.googleads.v15.enums.types import ( + sk_ad_network_source_type as gage_sk_ad_network_source_type, +) +from google.ads.googleads.v15.enums.types import ( + sk_ad_network_user_type as gage_sk_ad_network_user_type, +) +from google.ads.googleads.v15.enums.types import slot as gage_slot + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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_rating (int): + Activity rating. + + This field is a member of `oneof`_ ``_activity_rating``. + external_activity_id (str): + Advertiser supplied activity ID. + + This field is a member of `oneof`_ ``_external_activity_id``. + ad_destination_type (google.ads.googleads.v15.enums.types.AdDestinationTypeEnum.AdDestinationType): + Ad Destination type. + ad_network_type (google.ads.googleads.v15.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``. + 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.v15.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.v15.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.v15.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.v15.enums.types.ConversionAttributionEventTypeEnum.ConversionAttributionEventType): + Conversion attribution event type. + conversion_lag_bucket (google.ads.googleads.v15.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.v15.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.v15.enums.types.DayOfWeekEnum.DayOfWeek): + Day of the week, for example, MONDAY. + device (google.ads.googleads.v15.enums.types.DeviceEnum.Device): + Device to which metrics apply. + external_conversion_source (google.ads.googleads.v15.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.v15.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.v15.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.v15.enums.types.HotelRateTypeEnum.HotelRateType): + Hotel rate type. + hotel_price_bucket (google.ads.googleads.v15.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.v15.common.types.Keyword): + Keyword criterion. + 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.v15.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``. + placeholder_type (google.ads.googleads.v15.enums.types.PlaceholderTypeEnum.PlaceholderType): + Placeholder type. This is only used with feed + item metrics. + 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.v15.enums.types.ProductChannelEnum.ProductChannel): + Channel of the product. + product_channel_exclusivity (google.ads.googleads.v15.enums.types.ProductChannelExclusivityEnum.ProductChannelExclusivity): + Channel exclusivity of the product. + product_condition (google.ads.googleads.v15.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_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``. + recommendation_type (google.ads.googleads.v15.enums.types.RecommendationTypeEnum.RecommendationType): + Recommendation type. + search_engine_results_page_type (google.ads.googleads.v15.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.v15.enums.types.SearchTermMatchTypeEnum.SearchTermMatchType): + Match type of the keyword that triggered the + ad, including variants. + slot (google.ads.googleads.v15.enums.types.SlotEnum.Slot): + Position of the ad. + conversion_value_rule_primary_dimension (google.ads.googleads.v15.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 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_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_conversion_value``. + sk_ad_network_user_type (google.ads.googleads.v15.enums.types.SkAdNetworkUserTypeEnum.SkAdNetworkUserType): + iOS Store Kit Ad Network user type. + sk_ad_network_ad_event_type (google.ads.googleads.v15.enums.types.SkAdNetworkAdEventTypeEnum.SkAdNetworkAdEventType): + iOS Store Kit Ad Network ad event type. + sk_ad_network_source_app (google.ads.googleads.v15.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.v15.enums.types.SkAdNetworkAttributionCreditEnum.SkAdNetworkAttributionCredit): + iOS Store Kit Ad Network attribution credit + sk_ad_network_coarse_conversion_value (google.ads.googleads.v15.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.v15.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``. + asset_interaction_target (google.ads.googleads.v15.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.v15.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. + """ + + activity_account_id: int = proto.Field( + proto.INT64, + number=148, + optional=True, + ) + activity_rating: int = proto.Field( + proto.INT64, + number=149, + 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_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, + ) + 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", + ) + 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, + ) + placeholder_type: gage_placeholder_type.PlaceholderTypeEnum.PlaceholderType = proto.Field( + proto.ENUM, + number=20, + enum=gage_placeholder_type.PlaceholderTypeEnum.PlaceholderType, + ) + 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_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, + ) + 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, + ) + 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_conversion_value: int = proto.Field( + proto.INT64, + number=137, + 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, + ) + 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, + ) + + +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.v15.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.v15.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/v15/common/types/simulation.py b/google/ads/googleads/v15/common/types/simulation.py new file mode 100644 index 000000000..b495e922b --- /dev/null +++ b/google/ads/googleads/v15/common/types/simulation.py @@ -0,0 +1,755 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/common/types/tag_snippet.py b/google/ads/googleads/v15/common/types/tag_snippet.py new file mode 100644 index 000000000..353de4ea9 --- /dev/null +++ b/google/ads/googleads/v15/common/types/tag_snippet.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import tracking_code_page_format +from google.ads.googleads.v15.enums.types import tracking_code_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.TrackingCodeTypeEnum.TrackingCodeType): + The type of the generated tag snippets for + tracking conversions. + page_format (google.ads.googleads.v15.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/v15/common/types/targeting_setting.py b/google/ads/googleads/v15/common/types/targeting_setting.py new file mode 100644 index 000000000..722914fc7 --- /dev/null +++ b/google/ads/googleads/v15/common/types/targeting_setting.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + targeting_dimension as gage_targeting_dimension, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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.v15.common.types.TargetRestrictionOperation.Operator): + Type of list operation to perform. + value (google.ads.googleads.v15.common.types.TargetRestriction): + The target restriction being added to or + removed from the list. + """ + + class Operator(proto.Enum): + r"""The operator.""" + 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/v15/common/types/text_label.py b/google/ads/googleads/v15/common/types/text_label.py new file mode 100644 index 000000000..8de4db05a --- /dev/null +++ b/google/ads/googleads/v15/common/types/text_label.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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 RGB 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/v15/common/types/url_collection.py b/google/ads/googleads/v15/common/types/url_collection.py new file mode 100644 index 000000000..4b36d0b2a --- /dev/null +++ b/google/ads/googleads/v15/common/types/url_collection.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common", + marshal="google.ads.googleads.v15", + 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/v15/common/types/user_lists.py b/google/ads/googleads/v15/common/types/user_lists.py new file mode 100644 index 000000000..ba1208c16 --- /dev/null +++ b/google/ads/googleads/v15/common/types/user_lists.py @@ -0,0 +1,616 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import customer_match_upload_key_type +from google.ads.googleads.v15.enums.types import lookalike_expansion_level +from google.ads.googleads.v15.enums.types import user_list_crm_data_source_type +from google.ads.googleads.v15.enums.types import ( + user_list_date_rule_item_operator, +) +from google.ads.googleads.v15.enums.types import ( + user_list_flexible_rule_operator, +) +from google.ads.googleads.v15.enums.types import user_list_logical_rule_operator +from google.ads.googleads.v15.enums.types import ( + user_list_number_rule_item_operator, +) +from google.ads.googleads.v15.enums.types import user_list_prepopulation_status +from google.ads.googleads.v15.enums.types import user_list_rule_type +from google.ads.googleads.v15.enums.types import ( + user_list_string_rule_item_operator, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.enums.types.UserListFlexibleRuleOperatorEnum.UserListFlexibleRuleOperator): + Operator that defines how the inclusive + operands are combined. + inclusive_operands (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.enums.types.UserListLogicalRuleOperatorEnum.UserListLogicalRuleOperator): + The logical operator of the rule. + rule_operands (MutableSequence[google.ads.googleads.v15.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.v15.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/v15/common/types/value.py b/google/ads/googleads/v15/common/types/value.py new file mode 100644 index 000000000..ec23c2835 --- /dev/null +++ b/google/ads/googleads/v15/common/types/value.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.common", + marshal="google.ads.googleads.v15", + 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/v15/enums/__init__.py b/google/ads/googleads/v15/enums/__init__.py new file mode 100644 index 000000000..fa274b0bb --- /dev/null +++ b/google/ads/googleads/v15/enums/__init__.py @@ -0,0 +1,356 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +__all__ = ( + "AccessInvitationStatusEnum", + "AccessReasonEnum", + "AccessRoleEnum", + "AccountBudgetProposalStatusEnum", + "AccountBudgetProposalTypeEnum", + "AccountBudgetStatusEnum", + "AccountLinkStatusEnum", + "AdCustomizerPlaceholderFieldEnum", + "AdDestinationTypeEnum", + "AdGroupAdRotationModeEnum", + "AdGroupAdStatusEnum", + "AdGroupCriterionApprovalStatusEnum", + "AdGroupCriterionStatusEnum", + "AdGroupStatusEnum", + "AdGroupTypeEnum", + "AdNetworkTypeEnum", + "AdServingOptimizationStatusEnum", + "AdStrengthEnum", + "AdTypeEnum", + "AdvertisingChannelSubTypeEnum", + "AdvertisingChannelTypeEnum", + "AffiliateLocationFeedRelationshipTypeEnum", + "AffiliateLocationPlaceholderFieldEnum", + "AgeRangeTypeEnum", + "AndroidPrivacyInteractionTypeEnum", + "AndroidPrivacyNetworkTypeEnum", + "AppBiddingGoalEnum", + "AppCampaignAppStoreEnum", + "AppCampaignBiddingStrategyGoalTypeEnum", + "AppPaymentModelTypeEnum", + "AppPlaceholderFieldEnum", + "AppStoreEnum", + "AppUrlOperatingSystemTypeEnum", + "AssetAutomationStatusEnum", + "AssetAutomationTypeEnum", + "AssetFieldTypeEnum", + "AssetGroupPrimaryStatusEnum", + "AssetGroupPrimaryStatusReasonEnum", + "AssetGroupSignalApprovalStatusEnum", + "AssetGroupStatusEnum", + "AssetLinkPrimaryStatusEnum", + "AssetLinkPrimaryStatusReasonEnum", + "AssetLinkStatusEnum", + "AssetOfflineEvaluationErrorReasonsEnum", + "AssetPerformanceLabelEnum", + "AssetSetAssetStatusEnum", + "AssetSetLinkStatusEnum", + "AssetSetStatusEnum", + "AssetSetTypeEnum", + "AssetSourceEnum", + "AssetTypeEnum", + "AsyncActionStatusEnum", + "AttributionModelEnum", + "AudienceInsightsDimensionEnum", + "AudienceScopeEnum", + "AudienceStatusEnum", + "BatchJobStatusEnum", + "BidModifierSourceEnum", + "BiddingSourceEnum", + "BiddingStrategyStatusEnum", + "BiddingStrategySystemStatusEnum", + "BiddingStrategyTypeEnum", + "BillingSetupStatusEnum", + "BrandSafetySuitabilityEnum", + "BrandStateEnum", + "BudgetCampaignAssociationStatusEnum", + "BudgetDeliveryMethodEnum", + "BudgetPeriodEnum", + "BudgetStatusEnum", + "BudgetTypeEnum", + "CallConversionReportingStateEnum", + "CallPlaceholderFieldEnum", + "CallToActionTypeEnum", + "CallTrackingDisplayLocationEnum", + "CallTypeEnum", + "CalloutPlaceholderFieldEnum", + "CampaignCriterionStatusEnum", + "CampaignDraftStatusEnum", + "CampaignExperimentTypeEnum", + "CampaignGroupStatusEnum", + "CampaignPrimaryStatusEnum", + "CampaignPrimaryStatusReasonEnum", + "CampaignServingStatusEnum", + "CampaignSharedSetStatusEnum", + "CampaignStatusEnum", + "ChainRelationshipTypeEnum", + "ChangeClientTypeEnum", + "ChangeEventResourceTypeEnum", + "ChangeStatusOperationEnum", + "ChangeStatusResourceTypeEnum", + "ClickTypeEnum", + "CombinedAudienceStatusEnum", + "ConsentStatusEnum", + "ContentLabelTypeEnum", + "ConversionActionCategoryEnum", + "ConversionActionCountingTypeEnum", + "ConversionActionStatusEnum", + "ConversionActionTypeEnum", + "ConversionAdjustmentTypeEnum", + "ConversionAttributionEventTypeEnum", + "ConversionCustomVariableStatusEnum", + "ConversionEnvironmentEnum", + "ConversionLagBucketEnum", + "ConversionOrAdjustmentLagBucketEnum", + "ConversionOriginEnum", + "ConversionTrackingStatusEnum", + "ConversionValueRulePrimaryDimensionEnum", + "ConversionValueRuleSetStatusEnum", + "ConversionValueRuleStatusEnum", + "ConvertingUserPriorEngagementTypeAndLtvBucketEnum", + "CriterionCategoryChannelAvailabilityModeEnum", + "CriterionCategoryLocaleAvailabilityModeEnum", + "CriterionSystemServingStatusEnum", + "CriterionTypeEnum", + "CustomAudienceMemberTypeEnum", + "CustomAudienceStatusEnum", + "CustomAudienceTypeEnum", + "CustomConversionGoalStatusEnum", + "CustomInterestMemberTypeEnum", + "CustomInterestStatusEnum", + "CustomInterestTypeEnum", + "CustomPlaceholderFieldEnum", + "CustomerAcquisitionOptimizationModeEnum", + "CustomerMatchUploadKeyTypeEnum", + "CustomerPayPerConversionEligibilityFailureReasonEnum", + "CustomerStatusEnum", + "CustomizerAttributeStatusEnum", + "CustomizerAttributeTypeEnum", + "CustomizerValueStatusEnum", + "DataDrivenModelStatusEnum", + "DayOfWeekEnum", + "DeviceEnum", + "DisplayAdFormatSettingEnum", + "DisplayUploadProductTypeEnum", + "DistanceBucketEnum", + "DsaPageFeedCriterionFieldEnum", + "EducationPlaceholderFieldEnum", + "ExperimentMetricDirectionEnum", + "ExperimentMetricEnum", + "ExperimentStatusEnum", + "ExperimentTypeEnum", + "ExtensionSettingDeviceEnum", + "ExtensionTypeEnum", + "ExternalConversionSourceEnum", + "FeedAttributeTypeEnum", + "FeedItemQualityApprovalStatusEnum", + "FeedItemQualityDisapprovalReasonEnum", + "FeedItemSetStatusEnum", + "FeedItemSetStringFilterTypeEnum", + "FeedItemStatusEnum", + "FeedItemTargetDeviceEnum", + "FeedItemTargetStatusEnum", + "FeedItemTargetTypeEnum", + "FeedItemValidationStatusEnum", + "FeedLinkStatusEnum", + "FeedMappingCriterionTypeEnum", + "FeedMappingStatusEnum", + "FeedOriginEnum", + "FeedStatusEnum", + "FlightPlaceholderFieldEnum", + "FrequencyCapEventTypeEnum", + "FrequencyCapLevelEnum", + "FrequencyCapTimeUnitEnum", + "GenderTypeEnum", + "GeoTargetConstantStatusEnum", + "GeoTargetingRestrictionEnum", + "GeoTargetingTypeEnum", + "GoalConfigLevelEnum", + "GoogleAdsFieldCategoryEnum", + "GoogleAdsFieldDataTypeEnum", + "GoogleVoiceCallStatusEnum", + "HotelAssetSuggestionStatusEnum", + "HotelDateSelectionTypeEnum", + "HotelPlaceholderFieldEnum", + "HotelPriceBucketEnum", + "HotelRateTypeEnum", + "HotelReconciliationStatusEnum", + "ImagePlaceholderFieldEnum", + "IncomeRangeTypeEnum", + "InteractionEventTypeEnum", + "InteractionTypeEnum", + "InvoiceTypeEnum", + "JobPlaceholderFieldEnum", + "KeywordMatchTypeEnum", + "KeywordPlanAggregateMetricTypeEnum", + "KeywordPlanCompetitionLevelEnum", + "KeywordPlanConceptGroupTypeEnum", + "KeywordPlanForecastIntervalEnum", + "KeywordPlanKeywordAnnotationEnum", + "KeywordPlanNetworkEnum", + "LabelStatusEnum", + "LeadFormCallToActionTypeEnum", + "LeadFormDesiredIntentEnum", + "LeadFormFieldUserInputTypeEnum", + "LeadFormPostSubmitCallToActionTypeEnum", + "LegacyAppInstallAdAppStoreEnum", + "LinkedAccountTypeEnum", + "LinkedProductTypeEnum", + "ListingGroupFilterCustomAttributeIndexEnum", + "ListingGroupFilterListingSourceEnum", + "ListingGroupFilterProductCategoryLevelEnum", + "ListingGroupFilterProductChannelEnum", + "ListingGroupFilterProductConditionEnum", + "ListingGroupFilterProductTypeLevelEnum", + "ListingGroupFilterTypeEnum", + "ListingGroupTypeEnum", + "ListingTypeEnum", + "LocalPlaceholderFieldEnum", + "LocalServicesInsuranceRejectionReasonEnum", + "LocalServicesLeadConversationTypeEnum", + "LocalServicesLeadStatusEnum", + "LocalServicesLeadTypeEnum", + "LocalServicesLicenseRejectionReasonEnum", + "LocalServicesParticipantTypeEnum", + "LocalServicesVerificationArtifactStatusEnum", + "LocalServicesVerificationArtifactTypeEnum", + "LocalServicesVerificationStatusEnum", + "LocationExtensionTargetingCriterionFieldEnum", + "LocationGroupRadiusUnitsEnum", + "LocationOwnershipTypeEnum", + "LocationPlaceholderFieldEnum", + "LocationSourceTypeEnum", + "LocationStringFilterTypeEnum", + "LookalikeExpansionLevelEnum", + "ManagerLinkStatusEnum", + "MatchingFunctionContextTypeEnum", + "MatchingFunctionOperatorEnum", + "MediaTypeEnum", + "MessagePlaceholderFieldEnum", + "MimeTypeEnum", + "MinuteOfHourEnum", + "MobileAppVendorEnum", + "MobileDeviceTypeEnum", + "MonthOfYearEnum", + "NegativeGeoTargetTypeEnum", + "OfflineConversionDiagnosticStatusEnum", + "OfflineEventUploadClientEnum", + "OfflineUserDataJobFailureReasonEnum", + "OfflineUserDataJobMatchRateRangeEnum", + "OfflineUserDataJobStatusEnum", + "OfflineUserDataJobTypeEnum", + "OperatingSystemVersionOperatorTypeEnum", + "OptimizationGoalTypeEnum", + "ParentalStatusTypeEnum", + "PaymentModeEnum", + "PerformanceMaxUpgradeStatusEnum", + "PlaceholderTypeEnum", + "PlacementTypeEnum", + "PolicyApprovalStatusEnum", + "PolicyReviewStatusEnum", + "PolicyTopicEntryTypeEnum", + "PolicyTopicEvidenceDestinationMismatchUrlTypeEnum", + "PolicyTopicEvidenceDestinationNotWorkingDeviceEnum", + "PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum", + "PositiveGeoTargetTypeEnum", + "PriceExtensionPriceQualifierEnum", + "PriceExtensionPriceUnitEnum", + "PriceExtensionTypeEnum", + "PricePlaceholderFieldEnum", + "ProductCategoryLevelEnum", + "ProductCategoryStateEnum", + "ProductChannelEnum", + "ProductChannelExclusivityEnum", + "ProductConditionEnum", + "ProductCustomAttributeIndexEnum", + "ProductLinkInvitationStatusEnum", + "ProductTypeLevelEnum", + "PromotionExtensionDiscountModifierEnum", + "PromotionExtensionOccasionEnum", + "PromotionPlaceholderFieldEnum", + "ProximityRadiusUnitsEnum", + "QualityScoreBucketEnum", + "ReachPlanAgeRangeEnum", + "ReachPlanNetworkEnum", + "ReachPlanSurfaceEnum", + "RealEstatePlaceholderFieldEnum", + "RecommendationSubscriptionStatusEnum", + "RecommendationTypeEnum", + "ResourceChangeOperationEnum", + "ResourceLimitTypeEnum", + "ResponseContentTypeEnum", + "SearchEngineResultsPageTypeEnum", + "SearchTermMatchTypeEnum", + "SearchTermTargetingStatusEnum", + "SeasonalityEventScopeEnum", + "SeasonalityEventStatusEnum", + "ServedAssetFieldTypeEnum", + "SharedSetStatusEnum", + "SharedSetTypeEnum", + "ShoppingAddProductsToCampaignRecommendationEnum", + "SimulationModificationMethodEnum", + "SimulationTypeEnum", + "SitelinkPlaceholderFieldEnum", + "SkAdNetworkAdEventTypeEnum", + "SkAdNetworkAttributionCreditEnum", + "SkAdNetworkCoarseConversionValueEnum", + "SkAdNetworkSourceTypeEnum", + "SkAdNetworkUserTypeEnum", + "SlotEnum", + "SmartCampaignNotEligibleReasonEnum", + "SmartCampaignStatusEnum", + "SpendingLimitTypeEnum", + "StructuredSnippetPlaceholderFieldEnum", + "SummaryRowSettingEnum", + "SystemManagedResourceSourceEnum", + "TargetCpaOptInRecommendationGoalEnum", + "TargetFrequencyTimeUnitEnum", + "TargetImpressionShareLocationEnum", + "TargetingDimensionEnum", + "TimeTypeEnum", + "TrackingCodePageFormatEnum", + "TrackingCodeTypeEnum", + "TravelPlaceholderFieldEnum", + "UserIdentifierSourceEnum", + "UserInterestTaxonomyTypeEnum", + "UserListAccessStatusEnum", + "UserListClosingReasonEnum", + "UserListCrmDataSourceTypeEnum", + "UserListDateRuleItemOperatorEnum", + "UserListFlexibleRuleOperatorEnum", + "UserListLogicalRuleOperatorEnum", + "UserListMembershipStatusEnum", + "UserListNumberRuleItemOperatorEnum", + "UserListPrepopulationStatusEnum", + "UserListRuleTypeEnum", + "UserListSizeRangeEnum", + "UserListStringRuleItemOperatorEnum", + "UserListTypeEnum", + "ValueRuleDeviceTypeEnum", + "ValueRuleGeoLocationMatchTypeEnum", + "ValueRuleOperationEnum", + "ValueRuleSetAttachmentTypeEnum", + "ValueRuleSetDimensionEnum", + "VanityPharmaDisplayUrlModeEnum", + "VanityPharmaTextEnum", + "VideoThumbnailEnum", + "WebpageConditionOperandEnum", + "WebpageConditionOperatorEnum", +) diff --git a/google/ads/googleads/v15/enums/services/__init__.py b/google/ads/googleads/v15/enums/services/__init__.py new file mode 100644 index 000000000..89a37dc92 --- /dev/null +++ b/google/ads/googleads/v15/enums/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/v15/enums/types/__init__.py b/google/ads/googleads/v15/enums/types/__init__.py new file mode 100644 index 000000000..89a37dc92 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/v15/enums/types/access_invitation_status.py b/google/ads/googleads/v15/enums/types/access_invitation_status.py new file mode 100644 index 000000000..cb56fdf4f --- /dev/null +++ b/google/ads/googleads/v15/enums/types/access_invitation_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + DECLINED = 3 + EXPIRED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/access_reason.py b/google/ads/googleads/v15/enums/types/access_reason.py new file mode 100644 index 000000000..12902cdcb --- /dev/null +++ b/google/ads/googleads/v15/enums/types/access_reason.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/access_role.py b/google/ads/googleads/v15/enums/types/access_role.py new file mode 100644 index 000000000..1703359db --- /dev/null +++ b/google/ads/googleads/v15/enums/types/access_role.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/account_budget_proposal_status.py b/google/ads/googleads/v15/enums/types/account_budget_proposal_status.py new file mode 100644 index 000000000..54b6c18b2 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/account_budget_proposal_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AccountBudgetProposalStatusEnum", + }, +) + + +class AccountBudgetProposalStatusEnum(proto.Message): + r"""Message describing AccountBudgetProposal statuses.""" + + class AccountBudgetProposalStatus(proto.Enum): + r"""The possible statuses of an AccountBudgetProposal.""" + 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/v15/enums/types/account_budget_proposal_type.py b/google/ads/googleads/v15/enums/types/account_budget_proposal_type.py new file mode 100644 index 000000000..30b297713 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/account_budget_proposal_type.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AccountBudgetProposalTypeEnum", + }, +) + + +class AccountBudgetProposalTypeEnum(proto.Message): + r"""Message describing AccountBudgetProposal types.""" + + class AccountBudgetProposalType(proto.Enum): + r"""The possible types of an AccountBudgetProposal.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CREATE = 2 + UPDATE = 3 + END = 4 + REMOVE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/account_budget_status.py b/google/ads/googleads/v15/enums/types/account_budget_status.py new file mode 100644 index 000000000..ebdc0a811 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/account_budget_status.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AccountBudgetStatusEnum", + }, +) + + +class AccountBudgetStatusEnum(proto.Message): + r"""Message describing AccountBudget statuses.""" + + class AccountBudgetStatus(proto.Enum): + r"""The possible statuses of an AccountBudget.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + APPROVED = 3 + CANCELLED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/account_link_status.py b/google/ads/googleads/v15/enums/types/account_link_status.py new file mode 100644 index 000000000..8fa22c2c6 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/account_link_status.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/ad_customizer_placeholder_field.py b/google/ads/googleads/v15/enums/types/ad_customizer_placeholder_field.py new file mode 100644 index 000000000..dfb2a9e5e --- /dev/null +++ b/google/ads/googleads/v15/enums/types/ad_customizer_placeholder_field.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AdCustomizerPlaceholderFieldEnum", + }, +) + + +class AdCustomizerPlaceholderFieldEnum(proto.Message): + r"""Values for Ad Customizer placeholder fields.""" + + class AdCustomizerPlaceholderField(proto.Enum): + r"""Possible values for Ad Customizers placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + INTEGER = 2 + PRICE = 3 + DATE = 4 + STRING = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/ad_destination_type.py b/google/ads/googleads/v15/enums/types/ad_destination_type.py new file mode 100644 index 000000000..70baa5f5b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/ad_destination_type.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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""" + 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/v15/enums/types/ad_group_ad_rotation_mode.py b/google/ads/googleads/v15/enums/types/ad_group_ad_rotation_mode.py new file mode 100644 index 000000000..79743cd34 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/ad_group_ad_rotation_mode.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + OPTIMIZE = 2 + ROTATE_FOREVER = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/ad_group_ad_status.py b/google/ads/googleads/v15/enums/types/ad_group_ad_status.py new file mode 100644 index 000000000..84bcea743 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/ad_group_ad_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/ad_group_criterion_approval_status.py b/google/ads/googleads/v15/enums/types/ad_group_criterion_approval_status.py new file mode 100644 index 000000000..9322df57c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/ad_group_criterion_approval_status.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AdGroupCriterionApprovalStatusEnum", + }, +) + + +class AdGroupCriterionApprovalStatusEnum(proto.Message): + r"""Container for enum describing possible AdGroupCriterion + approval statuses. + + """ + + class AdGroupCriterionApprovalStatus(proto.Enum): + r"""Enumerates AdGroupCriterion approval statuses.""" + 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/v15/enums/types/ad_group_criterion_status.py b/google/ads/googleads/v15/enums/types/ad_group_criterion_status.py new file mode 100644 index 000000000..d548c95d2 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/ad_group_criterion_status.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AdGroupCriterionStatusEnum", + }, +) + + +class AdGroupCriterionStatusEnum(proto.Message): + r"""Message describing AdGroupCriterion statuses.""" + + class AdGroupCriterionStatus(proto.Enum): + r"""The possible statuses of an AdGroupCriterion.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/ad_group_status.py b/google/ads/googleads/v15/enums/types/ad_group_status.py new file mode 100644 index 000000000..983f81dfb --- /dev/null +++ b/google/ads/googleads/v15/enums/types/ad_group_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/ad_group_type.py b/google/ads/googleads/v15/enums/types/ad_group_type.py new file mode 100644 index 000000000..2d49eed54 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/ad_group_type.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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 + VIDEO_OUTSTREAM = 12 + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/ad_network_type.py b/google/ads/googleads/v15/enums/types/ad_network_type.py new file mode 100644 index 000000000..1e495f0a9 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/ad_network_type.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + SEARCH = 2 + SEARCH_PARTNERS = 3 + CONTENT = 4 + MIXED = 7 + YOUTUBE = 8 + GOOGLE_TV = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/ad_serving_optimization_status.py b/google/ads/googleads/v15/enums/types/ad_serving_optimization_status.py new file mode 100644 index 000000000..7bf1e94a3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/ad_serving_optimization_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AdServingOptimizationStatusEnum", + }, +) + + +class AdServingOptimizationStatusEnum(proto.Message): + r"""Possible ad serving statuses of a campaign.""" + + class AdServingOptimizationStatus(proto.Enum): + r"""Enum describing possible serving statuses.""" + 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/v15/enums/types/ad_strength.py b/google/ads/googleads/v15/enums/types/ad_strength.py new file mode 100644 index 000000000..31ef8a4bc --- /dev/null +++ b/google/ads/googleads/v15/enums/types/ad_strength.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/ad_type.py b/google/ads/googleads/v15/enums/types/ad_type.py new file mode 100644 index 000000000..b1d80891a --- /dev/null +++ b/google/ads/googleads/v15/enums/types/ad_type.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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_OUTSTREAM_AD = 27 + 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 + DISCOVERY_MULTI_ASSET_AD = 35 + DISCOVERY_CAROUSEL_AD = 36 + TRAVEL_AD = 37 + DISCOVERY_VIDEO_RESPONSIVE_AD = 38 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/advertising_channel_sub_type.py b/google/ads/googleads/v15/enums/types/advertising_channel_sub_type.py new file mode 100644 index 000000000..e114b5cc6 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/advertising_channel_sub_type.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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_OUTSTREAM = 9 + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/advertising_channel_type.py b/google/ads/googleads/v15/enums/types/advertising_channel_type.py new file mode 100644 index 000000000..1ae3a5945 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/advertising_channel_type.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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 + DISCOVERY = 12 + TRAVEL = 13 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/affiliate_location_feed_relationship_type.py b/google/ads/googleads/v15/enums/types/affiliate_location_feed_relationship_type.py new file mode 100644 index 000000000..403ad8f0c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/affiliate_location_feed_relationship_type.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AffiliateLocationFeedRelationshipTypeEnum", + }, +) + + +class AffiliateLocationFeedRelationshipTypeEnum(proto.Message): + r"""Container for enum describing possible values for a + relationship type for an affiliate location feed. + + """ + + class AffiliateLocationFeedRelationshipType(proto.Enum): + r"""Possible values for a relationship type for an affiliate + location feed. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + GENERAL_RETAILER = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/affiliate_location_placeholder_field.py b/google/ads/googleads/v15/enums/types/affiliate_location_placeholder_field.py new file mode 100644 index 000000000..3227ba53b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/affiliate_location_placeholder_field.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AffiliateLocationPlaceholderFieldEnum", + }, +) + + +class AffiliateLocationPlaceholderFieldEnum(proto.Message): + r"""Values for Affiliate Location placeholder fields.""" + + class AffiliateLocationPlaceholderField(proto.Enum): + r"""Possible values for Affiliate Location placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + BUSINESS_NAME = 2 + ADDRESS_LINE_1 = 3 + ADDRESS_LINE_2 = 4 + CITY = 5 + PROVINCE = 6 + POSTAL_CODE = 7 + COUNTRY_CODE = 8 + PHONE_NUMBER = 9 + LANGUAGE_CODE = 10 + CHAIN_ID = 11 + CHAIN_NAME = 12 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/age_range_type.py b/google/ads/googleads/v15/enums/types/age_range_type.py new file mode 100644 index 000000000..41c9a2ec0 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/age_range_type.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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). + """ + 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/v15/enums/types/android_privacy_interaction_type.py b/google/ads/googleads/v15/enums/types/android_privacy_interaction_type.py new file mode 100644 index 000000000..64c222563 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/android_privacy_interaction_type.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AndroidPrivacyInteractionTypeEnum", + }, +) + + +class AndroidPrivacyInteractionTypeEnum(proto.Message): + r"""The interaction type enum for Android privacy shared key.""" + + class AndroidPrivacyInteractionType(proto.Enum): + r"""Enumerates interaction types""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CLICK = 2 + ENGAGED_VIEW = 3 + VIEW = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/android_privacy_network_type.py b/google/ads/googleads/v15/enums/types/android_privacy_network_type.py new file mode 100644 index 000000000..d7081171c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/android_privacy_network_type.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AndroidPrivacyNetworkTypeEnum", + }, +) + + +class AndroidPrivacyNetworkTypeEnum(proto.Message): + r"""The network type enum for Android privacy shared key.""" + + class AndroidPrivacyNetworkType(proto.Enum): + r"""Enumerates network types""" + UNSPECIFIED = 0 + UNKNOWN = 1 + SEARCH = 2 + DISPLAY = 3 + YOUTUBE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/app_bidding_goal.py b/google/ads/googleads/v15/enums/types/app_bidding_goal.py new file mode 100644 index 000000000..f65e82fcd --- /dev/null +++ b/google/ads/googleads/v15/enums/types/app_bidding_goal.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/app_campaign_app_store.py b/google/ads/googleads/v15/enums/types/app_campaign_app_store.py new file mode 100644 index 000000000..50e7ced77 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/app_campaign_app_store.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + APPLE_APP_STORE = 2 + GOOGLE_APP_STORE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/app_campaign_bidding_strategy_goal_type.py b/google/ads/googleads/v15/enums/types/app_campaign_bidding_strategy_goal_type.py new file mode 100644 index 000000000..699449c5f --- /dev/null +++ b/google/ads/googleads/v15/enums/types/app_campaign_bidding_strategy_goal_type.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/app_payment_model_type.py b/google/ads/googleads/v15/enums/types/app_payment_model_type.py new file mode 100644 index 000000000..a6f59b0f1 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/app_payment_model_type.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PAID = 30 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/app_placeholder_field.py b/google/ads/googleads/v15/enums/types/app_placeholder_field.py new file mode 100644 index 000000000..9bfc5a517 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/app_placeholder_field.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AppPlaceholderFieldEnum", + }, +) + + +class AppPlaceholderFieldEnum(proto.Message): + r"""Values for App placeholder fields.""" + + class AppPlaceholderField(proto.Enum): + r"""Possible values for App placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + STORE = 2 + ID = 3 + LINK_TEXT = 4 + URL = 5 + FINAL_URLS = 6 + FINAL_MOBILE_URLS = 7 + TRACKING_URL = 8 + FINAL_URL_SUFFIX = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/app_store.py b/google/ads/googleads/v15/enums/types/app_store.py new file mode 100644 index 000000000..77b3da8d0 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/app_store.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AppStoreEnum", + }, +) + + +class AppStoreEnum(proto.Message): + r"""Container for enum describing app store type in an app + extension. + + """ + + class AppStore(proto.Enum): + r"""App store type in an app extension.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + APPLE_ITUNES = 2 + GOOGLE_PLAY = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/app_url_operating_system_type.py b/google/ads/googleads/v15/enums/types/app_url_operating_system_type.py new file mode 100644 index 000000000..9dc9c1f62 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/app_url_operating_system_type.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AppUrlOperatingSystemTypeEnum", + }, +) + + +class AppUrlOperatingSystemTypeEnum(proto.Message): + r"""The possible OS types for a deeplink AppUrl.""" + + class AppUrlOperatingSystemType(proto.Enum): + r"""Operating System""" + UNSPECIFIED = 0 + UNKNOWN = 1 + IOS = 2 + ANDROID = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/asset_automation_status.py b/google/ads/googleads/v15/enums/types/asset_automation_status.py new file mode 100644 index 000000000..85e2422af --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_automation_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + OPTED_IN = 2 + OPTED_OUT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/asset_automation_type.py b/google/ads/googleads/v15/enums/types/asset_automation_type.py new file mode 100644 index 000000000..6cab572ab --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_automation_type.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + TEXT_ASSET_AUTOMATION = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/asset_field_type.py b/google/ads/googleads/v15/enums/types/asset_field_type.py new file mode 100644 index 000000000..c12051997 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_field_type.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/asset_group_primary_status.py b/google/ads/googleads/v15/enums/types/asset_group_primary_status.py new file mode 100644 index 000000000..26d4e1ce4 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_group_primary_status.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/asset_group_primary_status_reason.py b/google/ads/googleads/v15/enums/types/asset_group_primary_status_reason.py new file mode 100644 index 000000000..49e137f35 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_group_primary_status_reason.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/asset_group_signal_approval_status.py b/google/ads/googleads/v15/enums/types/asset_group_signal_approval_status.py new file mode 100644 index 000000000..87ea8bf59 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_group_signal_approval_status.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + APPROVED = 2 + LIMITED = 3 + DISAPPROVED = 4 + UNDER_REVIEW = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/asset_group_status.py b/google/ads/googleads/v15/enums/types/asset_group_status.py new file mode 100644 index 000000000..10ea6f6ed --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_group_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/asset_link_primary_status.py b/google/ads/googleads/v15/enums/types/asset_link_primary_status.py new file mode 100644 index 000000000..e38d79a49 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_link_primary_status.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/asset_link_primary_status_reason.py b/google/ads/googleads/v15/enums/types/asset_link_primary_status_reason.py new file mode 100644 index 000000000..2793b5c0f --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_link_primary_status_reason.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/asset_link_status.py b/google/ads/googleads/v15/enums/types/asset_link_status.py new file mode 100644 index 000000000..8a5f95b41 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_link_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + PAUSED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/asset_offline_evaluation_error_reasons.py b/google/ads/googleads/v15/enums/types/asset_offline_evaluation_error_reasons.py new file mode 100644 index 000000000..0711e8776 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_offline_evaluation_error_reasons.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/asset_performance_label.py b/google/ads/googleads/v15/enums/types/asset_performance_label.py new file mode 100644 index 000000000..0c2cca70c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_performance_label.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + LEARNING = 3 + LOW = 4 + GOOD = 5 + BEST = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/asset_set_asset_status.py b/google/ads/googleads/v15/enums/types/asset_set_asset_status.py new file mode 100644 index 000000000..ce244b22b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_set_asset_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/asset_set_link_status.py b/google/ads/googleads/v15/enums/types/asset_set_link_status.py new file mode 100644 index 000000000..772e91fa2 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_set_link_status.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/asset_set_status.py b/google/ads/googleads/v15/enums/types/asset_set_status.py new file mode 100644 index 000000000..708c1329d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_set_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/asset_set_type.py b/google/ads/googleads/v15/enums/types/asset_set_type.py new file mode 100644 index 000000000..db3954a94 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_set_type.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/asset_source.py b/google/ads/googleads/v15/enums/types/asset_source.py new file mode 100644 index 000000000..fdd2751b5 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_source.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ADVERTISER = 2 + AUTOMATICALLY_CREATED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/asset_type.py b/google/ads/googleads/v15/enums/types/asset_type.py new file mode 100644 index 000000000..1b50c0386 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/asset_type.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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 + DISCOVERY_CAROUSEL_CARD = 23 + DYNAMIC_TRAVEL = 24 + DYNAMIC_LOCAL = 25 + DYNAMIC_JOBS = 26 + LOCATION = 27 + HOTEL_PROPERTY = 28 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/async_action_status.py b/google/ads/googleads/v15/enums/types/async_action_status.py new file mode 100644 index 000000000..2b1b81373 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/async_action_status.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/attribution_model.py b/google/ads/googleads/v15/enums/types/attribution_model.py new file mode 100644 index 000000000..88aa4aa27 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/attribution_model.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/audience_insights_dimension.py b/google/ads/googleads/v15/enums/types/audience_insights_dimension.py new file mode 100644 index 000000000..1b9f76e5b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/audience_insights_dimension.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CATEGORY = 2 + KNOWLEDGE_GRAPH = 3 + GEO_TARGET_COUNTRY = 4 + SUB_COUNTRY_LOCATION = 5 + YOUTUBE_CHANNEL = 6 + YOUTUBE_DYNAMIC_LINEUP = 7 + AFFINITY_USER_INTEREST = 8 + IN_MARKET_USER_INTEREST = 9 + PARENTAL_STATUS = 10 + INCOME_RANGE = 11 + AGE_RANGE = 12 + GENDER = 13 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/audience_scope.py b/google/ads/googleads/v15/enums/types/audience_scope.py new file mode 100644 index 000000000..8bc86f4bd --- /dev/null +++ b/google/ads/googleads/v15/enums/types/audience_scope.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER = 2 + ASSET_GROUP = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/audience_status.py b/google/ads/googleads/v15/enums/types/audience_status.py new file mode 100644 index 000000000..81568f52b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/audience_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "AudienceStatusEnum", + }, +) + + +class AudienceStatusEnum(proto.Message): + r"""The status of audience.""" + + class AudienceStatus(proto.Enum): + r"""Enum containing possible audience status types.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/batch_job_status.py b/google/ads/googleads/v15/enums/types/batch_job_status.py new file mode 100644 index 000000000..5edfd42b6 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/batch_job_status.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "BatchJobStatusEnum", + }, +) + + +class BatchJobStatusEnum(proto.Message): + r"""Container for enum describing possible batch job statuses.""" + + class BatchJobStatus(proto.Enum): + r"""The batch job statuses.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + RUNNING = 3 + DONE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/bid_modifier_source.py b/google/ads/googleads/v15/enums/types/bid_modifier_source.py new file mode 100644 index 000000000..8b56b691e --- /dev/null +++ b/google/ads/googleads/v15/enums/types/bid_modifier_source.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGN = 2 + AD_GROUP = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/bidding_source.py b/google/ads/googleads/v15/enums/types/bidding_source.py new file mode 100644 index 000000000..f73840cf7 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/bidding_source.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/bidding_strategy_status.py b/google/ads/googleads/v15/enums/types/bidding_strategy_status.py new file mode 100644 index 000000000..73972133d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/bidding_strategy_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "BiddingStrategyStatusEnum", + }, +) + + +class BiddingStrategyStatusEnum(proto.Message): + r"""Message describing BiddingStrategy statuses.""" + + class BiddingStrategyStatus(proto.Enum): + r"""The possible statuses of a BiddingStrategy.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/bidding_strategy_system_status.py b/google/ads/googleads/v15/enums/types/bidding_strategy_system_status.py new file mode 100644 index 000000000..98e302d58 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/bidding_strategy_system_status.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "BiddingStrategySystemStatusEnum", + }, +) + + +class BiddingStrategySystemStatusEnum(proto.Message): + r"""Message describing BiddingStrategy system statuses.""" + + class BiddingStrategySystemStatus(proto.Enum): + r"""The possible system statuses of a BiddingStrategy.""" + 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/v15/enums/types/bidding_strategy_type.py b/google/ads/googleads/v15/enums/types/bidding_strategy_type.py new file mode 100644 index 000000000..29000e574 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/bidding_strategy_type.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + COMMISSION = 16 + ENHANCED_CPC = 2 + 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_CPM = 14 + 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/v15/enums/types/billing_setup_status.py b/google/ads/googleads/v15/enums/types/billing_setup_status.py new file mode 100644 index 000000000..ce6abdae3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/billing_setup_status.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "BillingSetupStatusEnum", + }, +) + + +class BillingSetupStatusEnum(proto.Message): + r"""Message describing BillingSetup statuses.""" + + class BillingSetupStatus(proto.Enum): + r"""The possible statuses of a BillingSetup.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + APPROVED_HELD = 3 + APPROVED = 4 + CANCELLED = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/brand_safety_suitability.py b/google/ads/googleads/v15/enums/types/brand_safety_suitability.py new file mode 100644 index 000000000..2207b5a8a --- /dev/null +++ b/google/ads/googleads/v15/enums/types/brand_safety_suitability.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + EXPANDED_INVENTORY = 2 + STANDARD_INVENTORY = 3 + LIMITED_INVENTORY = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/brand_state.py b/google/ads/googleads/v15/enums/types/brand_state.py new file mode 100644 index 000000000..ea766611b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/brand_state.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "BrandStateEnum", + }, +) + + +class BrandStateEnum(proto.Message): + r"""Container for enum describing possible brand states.""" + + class BrandState(proto.Enum): + r"""Enumeration of different brand states.""" + 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/v15/enums/types/budget_campaign_association_status.py b/google/ads/googleads/v15/enums/types/budget_campaign_association_status.py new file mode 100644 index 000000000..ae1565bd3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/budget_campaign_association_status.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/budget_delivery_method.py b/google/ads/googleads/v15/enums/types/budget_delivery_method.py new file mode 100644 index 000000000..b3ac7a6bd --- /dev/null +++ b/google/ads/googleads/v15/enums/types/budget_delivery_method.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + STANDARD = 2 + ACCELERATED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/budget_period.py b/google/ads/googleads/v15/enums/types/budget_period.py new file mode 100644 index 000000000..2d2f39d34 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/budget_period.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "BudgetPeriodEnum", + }, +) + + +class BudgetPeriodEnum(proto.Message): + r"""Message describing Budget period.""" + + class BudgetPeriod(proto.Enum): + r"""Possible period of a Budget.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + DAILY = 2 + CUSTOM_PERIOD = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/budget_status.py b/google/ads/googleads/v15/enums/types/budget_status.py new file mode 100644 index 000000000..d45efcb8b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/budget_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "BudgetStatusEnum", + }, +) + + +class BudgetStatusEnum(proto.Message): + r"""Message describing a Budget status""" + + class BudgetStatus(proto.Enum): + r"""Possible statuses of a Budget.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/budget_type.py b/google/ads/googleads/v15/enums/types/budget_type.py new file mode 100644 index 000000000..2c76433c9 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/budget_type.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "BudgetTypeEnum", + }, +) + + +class BudgetTypeEnum(proto.Message): + r"""Describes Budget types.""" + + class BudgetType(proto.Enum): + r"""Possible Budget types.""" + 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/v15/enums/types/call_conversion_reporting_state.py b/google/ads/googleads/v15/enums/types/call_conversion_reporting_state.py new file mode 100644 index 000000000..1aa970cb0 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/call_conversion_reporting_state.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/call_placeholder_field.py b/google/ads/googleads/v15/enums/types/call_placeholder_field.py new file mode 100644 index 000000000..f32e1512e --- /dev/null +++ b/google/ads/googleads/v15/enums/types/call_placeholder_field.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "CallPlaceholderFieldEnum", + }, +) + + +class CallPlaceholderFieldEnum(proto.Message): + r"""Values for Call placeholder fields.""" + + class CallPlaceholderField(proto.Enum): + r"""Possible values for Call placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PHONE_NUMBER = 2 + COUNTRY_CODE = 3 + TRACKED = 4 + CONVERSION_TYPE_ID = 5 + CONVERSION_REPORTING_STATE = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/call_to_action_type.py b/google/ads/googleads/v15/enums/types/call_to_action_type.py new file mode 100644 index 000000000..f6878ad03 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/call_to_action_type.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/call_tracking_display_location.py b/google/ads/googleads/v15/enums/types/call_tracking_display_location.py new file mode 100644 index 000000000..564e5f681 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/call_tracking_display_location.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + AD = 2 + LANDING_PAGE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/call_type.py b/google/ads/googleads/v15/enums/types/call_type.py new file mode 100644 index 000000000..e29991858 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/call_type.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + MANUALLY_DIALED = 2 + HIGH_END_MOBILE_SEARCH = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/callout_placeholder_field.py b/google/ads/googleads/v15/enums/types/callout_placeholder_field.py new file mode 100644 index 000000000..397b8192a --- /dev/null +++ b/google/ads/googleads/v15/enums/types/callout_placeholder_field.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "CalloutPlaceholderFieldEnum", + }, +) + + +class CalloutPlaceholderFieldEnum(proto.Message): + r"""Values for Callout placeholder fields.""" + + class CalloutPlaceholderField(proto.Enum): + r"""Possible values for Callout placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CALLOUT_TEXT = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/campaign_criterion_status.py b/google/ads/googleads/v15/enums/types/campaign_criterion_status.py new file mode 100644 index 000000000..dbc87fa29 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/campaign_criterion_status.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "CampaignCriterionStatusEnum", + }, +) + + +class CampaignCriterionStatusEnum(proto.Message): + r"""Message describing CampaignCriterion statuses.""" + + class CampaignCriterionStatus(proto.Enum): + r"""The possible statuses of a CampaignCriterion.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/campaign_draft_status.py b/google/ads/googleads/v15/enums/types/campaign_draft_status.py new file mode 100644 index 000000000..18b9bebc4 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/campaign_draft_status.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/campaign_experiment_type.py b/google/ads/googleads/v15/enums/types/campaign_experiment_type.py new file mode 100644 index 000000000..240ea83e5 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/campaign_experiment_type.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + BASE = 2 + DRAFT = 3 + EXPERIMENT = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/campaign_group_status.py b/google/ads/googleads/v15/enums/types/campaign_group_status.py new file mode 100644 index 000000000..3451e7c7c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/campaign_group_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "CampaignGroupStatusEnum", + }, +) + + +class CampaignGroupStatusEnum(proto.Message): + r"""Message describing CampaignGroup statuses.""" + + class CampaignGroupStatus(proto.Enum): + r"""Possible statuses of a CampaignGroup.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/campaign_primary_status.py b/google/ads/googleads/v15/enums/types/campaign_primary_status.py new file mode 100644 index 000000000..8181a3d90 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/campaign_primary_status.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/campaign_primary_status_reason.py b/google/ads/googleads/v15/enums/types/campaign_primary_status_reason.py new file mode 100644 index 000000000..db23816c8 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/campaign_primary_status_reason.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/campaign_serving_status.py b/google/ads/googleads/v15/enums/types/campaign_serving_status.py new file mode 100644 index 000000000..1bbc1cd93 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/campaign_serving_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "CampaignServingStatusEnum", + }, +) + + +class CampaignServingStatusEnum(proto.Message): + r"""Message describing Campaign serving statuses.""" + + class CampaignServingStatus(proto.Enum): + r"""Possible serving statuses of a campaign.""" + 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/v15/enums/types/campaign_shared_set_status.py b/google/ads/googleads/v15/enums/types/campaign_shared_set_status.py new file mode 100644 index 000000000..0d1186790 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/campaign_shared_set_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/campaign_status.py b/google/ads/googleads/v15/enums/types/campaign_status.py new file mode 100644 index 000000000..aae23699d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/campaign_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/chain_relationship_type.py b/google/ads/googleads/v15/enums/types/chain_relationship_type.py new file mode 100644 index 000000000..7936ebbd0 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/chain_relationship_type.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + AUTO_DEALERS = 2 + GENERAL_RETAILERS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/change_client_type.py b/google/ads/googleads/v15/enums/types/change_client_type.py new file mode 100644 index 000000000..5a74bbb28 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/change_client_type.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/change_event_resource_type.py b/google/ads/googleads/v15/enums/types/change_event_resource_type.py new file mode 100644 index 000000000..1d64e6841 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/change_event_resource_type.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/change_status_operation.py b/google/ads/googleads/v15/enums/types/change_status_operation.py new file mode 100644 index 000000000..5b58a3bf3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/change_status_operation.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ADDED = 2 + CHANGED = 3 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/change_status_resource_type.py b/google/ads/googleads/v15/enums/types/change_status_resource_type.py new file mode 100644 index 000000000..26cbb6e20 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/change_status_resource_type.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + AD_GROUP = 3 + AD_GROUP_AD = 4 + AD_GROUP_CRITERION = 5 + CAMPAIGN = 6 + CAMPAIGN_CRITERION = 7 + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/click_type.py b/google/ads/googleads/v15/enums/types/click_type.py new file mode 100644 index 000000000..a40d9b00f --- /dev/null +++ b/google/ads/googleads/v15/enums/types/click_type.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/combined_audience_status.py b/google/ads/googleads/v15/enums/types/combined_audience_status.py new file mode 100644 index 000000000..e76e70952 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/combined_audience_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "CombinedAudienceStatusEnum", + }, +) + + +class CombinedAudienceStatusEnum(proto.Message): + r"""The status of combined audience.""" + + class CombinedAudienceStatus(proto.Enum): + r"""Enum containing possible combined audience status types.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/consent_status.py b/google/ads/googleads/v15/enums/types/consent_status.py new file mode 100644 index 000000000..d8b10abd1 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/consent_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "ConsentStatusEnum", + }, +) + + +class ConsentStatusEnum(proto.Message): + r"""Enums represent consent status.""" + + class ConsentStatus(proto.Enum): + r"""Consent status""" + UNSPECIFIED = 0 + UNKNOWN = 1 + GRANTED = 2 + DENIED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/content_label_type.py b/google/ads/googleads/v15/enums/types/content_label_type.py new file mode 100644 index 000000000..85d8a39f2 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/content_label_type.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/conversion_action_category.py b/google/ads/googleads/v15/enums/types/conversion_action_category.py new file mode 100644 index 000000000..af6323c2a --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_action_category.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/conversion_action_counting_type.py b/google/ads/googleads/v15/enums/types/conversion_action_counting_type.py new file mode 100644 index 000000000..4c4c6e558 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_action_counting_type.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + ONE_PER_CLICK = 2 + MANY_PER_CLICK = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/conversion_action_status.py b/google/ads/googleads/v15/enums/types/conversion_action_status.py new file mode 100644 index 000000000..a2eee8a7b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_action_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + HIDDEN = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/conversion_action_type.py b/google/ads/googleads/v15/enums/types/conversion_action_type.py new file mode 100644 index 000000000..2888b1b3d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_action_type.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/conversion_adjustment_type.py b/google/ads/googleads/v15/enums/types/conversion_adjustment_type.py new file mode 100644 index 000000000..21c64cf29 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_adjustment_type.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + RETRACTION = 2 + RESTATEMENT = 3 + ENHANCEMENT = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/conversion_attribution_event_type.py b/google/ads/googleads/v15/enums/types/conversion_attribution_event_type.py new file mode 100644 index 000000000..240c92da4 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_attribution_event_type.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + IMPRESSION = 2 + INTERACTION = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/conversion_custom_variable_status.py b/google/ads/googleads/v15/enums/types/conversion_custom_variable_status.py new file mode 100644 index 000000000..9d140c0c3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_custom_variable_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ACTIVATION_NEEDED = 2 + ENABLED = 3 + PAUSED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/conversion_environment_enum.py b/google/ads/googleads/v15/enums/types/conversion_environment_enum.py new file mode 100644 index 000000000..3792df4fe --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_environment_enum.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + APP = 2 + WEB = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/conversion_lag_bucket.py b/google/ads/googleads/v15/enums/types/conversion_lag_bucket.py new file mode 100644 index 000000000..fde8a07d6 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_lag_bucket.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/conversion_or_adjustment_lag_bucket.py b/google/ads/googleads/v15/enums/types/conversion_or_adjustment_lag_bucket.py new file mode 100644 index 000000000..6fc11431d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_or_adjustment_lag_bucket.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/conversion_origin.py b/google/ads/googleads/v15/enums/types/conversion_origin.py new file mode 100644 index 000000000..391cf4eda --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_origin.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/conversion_tracking_status_enum.py b/google/ads/googleads/v15/enums/types/conversion_tracking_status_enum.py new file mode 100644 index 000000000..5742422b4 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_tracking_status_enum.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/conversion_value_rule_primary_dimension.py b/google/ads/googleads/v15/enums/types/conversion_value_rule_primary_dimension.py new file mode 100644 index 000000000..257d23e62 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_value_rule_primary_dimension.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + NO_RULE_APPLIED = 2 + ORIGINAL = 3 + NEW_VS_RETURNING_USER = 4 + GEO_LOCATION = 5 + DEVICE = 6 + AUDIENCE = 7 + MULTIPLE = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/conversion_value_rule_set_status.py b/google/ads/googleads/v15/enums/types/conversion_value_rule_set_status.py new file mode 100644 index 000000000..b3e2e10a3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_value_rule_set_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + PAUSED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/conversion_value_rule_status.py b/google/ads/googleads/v15/enums/types/conversion_value_rule_status.py new file mode 100644 index 000000000..4f1392d0d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/conversion_value_rule_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + PAUSED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/converting_user_prior_engagement_type_and_ltv_bucket.py b/google/ads/googleads/v15/enums/types/converting_user_prior_engagement_type_and_ltv_bucket.py new file mode 100644 index 000000000..1456cd3d7 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/converting_user_prior_engagement_type_and_ltv_bucket.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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 + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + NEW = 2 + RETURNING = 3 + NEW_AND_HIGH_LTV = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/criterion_category_channel_availability_mode.py b/google/ads/googleads/v15/enums/types/criterion_category_channel_availability_mode.py new file mode 100644 index 000000000..7f0a01ba9 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/criterion_category_channel_availability_mode.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/criterion_category_locale_availability_mode.py b/google/ads/googleads/v15/enums/types/criterion_category_locale_availability_mode.py new file mode 100644 index 000000000..10df8ee6e --- /dev/null +++ b/google/ads/googleads/v15/enums/types/criterion_category_locale_availability_mode.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/criterion_system_serving_status.py b/google/ads/googleads/v15/enums/types/criterion_system_serving_status.py new file mode 100644 index 000000000..40a87cbd3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/criterion_system_serving_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ELIGIBLE = 2 + RARELY_SERVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/criterion_type.py b/google/ads/googleads/v15/enums/types/criterion_type.py new file mode 100644 index 000000000..78b38023f --- /dev/null +++ b/google/ads/googleads/v15/enums/types/criterion_type.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "CriterionTypeEnum", + }, +) + + +class CriterionTypeEnum(proto.Message): + r"""The possible types of a criterion.""" + + class CriterionType(proto.Enum): + r"""Enum describing possible criterion types.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/custom_audience_member_type.py b/google/ads/googleads/v15/enums/types/custom_audience_member_type.py new file mode 100644 index 000000000..60f41c7bf --- /dev/null +++ b/google/ads/googleads/v15/enums/types/custom_audience_member_type.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + KEYWORD = 2 + URL = 3 + PLACE_CATEGORY = 4 + APP = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/custom_audience_status.py b/google/ads/googleads/v15/enums/types/custom_audience_status.py new file mode 100644 index 000000000..451750edd --- /dev/null +++ b/google/ads/googleads/v15/enums/types/custom_audience_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "CustomAudienceStatusEnum", + }, +) + + +class CustomAudienceStatusEnum(proto.Message): + r"""The status of custom audience.""" + + class CustomAudienceStatus(proto.Enum): + r"""Enum containing possible custom audience statuses.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/custom_audience_type.py b/google/ads/googleads/v15/enums/types/custom_audience_type.py new file mode 100644 index 000000000..2d65e07d3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/custom_audience_type.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "CustomAudienceTypeEnum", + }, +) + + +class CustomAudienceTypeEnum(proto.Message): + r"""The types of custom audience.""" + + class CustomAudienceType(proto.Enum): + r"""Enum containing possible custom audience types.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + AUTO = 2 + INTEREST = 3 + PURCHASE_INTENT = 4 + SEARCH = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/custom_conversion_goal_status.py b/google/ads/googleads/v15/enums/types/custom_conversion_goal_status.py new file mode 100644 index 000000000..d95e58760 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/custom_conversion_goal_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/custom_interest_member_type.py b/google/ads/googleads/v15/enums/types/custom_interest_member_type.py new file mode 100644 index 000000000..cb43853ff --- /dev/null +++ b/google/ads/googleads/v15/enums/types/custom_interest_member_type.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + KEYWORD = 2 + URL = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/custom_interest_status.py b/google/ads/googleads/v15/enums/types/custom_interest_status.py new file mode 100644 index 000000000..6f755d4f6 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/custom_interest_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "CustomInterestStatusEnum", + }, +) + + +class CustomInterestStatusEnum(proto.Message): + r"""The status of custom interest.""" + + class CustomInterestStatus(proto.Enum): + r"""Enum containing possible custom interest types.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/custom_interest_type.py b/google/ads/googleads/v15/enums/types/custom_interest_type.py new file mode 100644 index 000000000..cc8eea02a --- /dev/null +++ b/google/ads/googleads/v15/enums/types/custom_interest_type.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "CustomInterestTypeEnum", + }, +) + + +class CustomInterestTypeEnum(proto.Message): + r"""The types of custom interest.""" + + class CustomInterestType(proto.Enum): + r"""Enum containing possible custom interest types.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOM_AFFINITY = 2 + CUSTOM_INTENT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/custom_placeholder_field.py b/google/ads/googleads/v15/enums/types/custom_placeholder_field.py new file mode 100644 index 000000000..b5fb1e48e --- /dev/null +++ b/google/ads/googleads/v15/enums/types/custom_placeholder_field.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "CustomPlaceholderFieldEnum", + }, +) + + +class CustomPlaceholderFieldEnum(proto.Message): + r"""Values for Custom placeholder fields. + For more information about dynamic remarketing feeds, see + https://support.google.com/google-ads/answer/6053288. + + """ + + class CustomPlaceholderField(proto.Enum): + r"""Possible values for Custom placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ID = 2 + ID2 = 3 + ITEM_TITLE = 4 + ITEM_SUBTITLE = 5 + ITEM_DESCRIPTION = 6 + ITEM_ADDRESS = 7 + PRICE = 8 + FORMATTED_PRICE = 9 + SALE_PRICE = 10 + FORMATTED_SALE_PRICE = 11 + IMAGE_URL = 12 + ITEM_CATEGORY = 13 + FINAL_URLS = 14 + FINAL_MOBILE_URLS = 15 + TRACKING_URL = 16 + CONTEXTUAL_KEYWORDS = 17 + ANDROID_APP_LINK = 18 + SIMILAR_IDS = 19 + IOS_APP_LINK = 20 + IOS_APP_STORE_ID = 21 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/customer_acquisition_optimization_mode.py b/google/ads/googleads/v15/enums/types/customer_acquisition_optimization_mode.py new file mode 100644 index 000000000..4e68a9cbc --- /dev/null +++ b/google/ads/googleads/v15/enums/types/customer_acquisition_optimization_mode.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/customer_match_upload_key_type.py b/google/ads/googleads/v15/enums/types/customer_match_upload_key_type.py new file mode 100644 index 000000000..efaa03f9c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/customer_match_upload_key_type.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/customer_pay_per_conversion_eligibility_failure_reason.py b/google/ads/googleads/v15/enums/types/customer_pay_per_conversion_eligibility_failure_reason.py new file mode 100644 index 000000000..aebd2b47a --- /dev/null +++ b/google/ads/googleads/v15/enums/types/customer_pay_per_conversion_eligibility_failure_reason.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/customer_status.py b/google/ads/googleads/v15/enums/types/customer_status.py new file mode 100644 index 000000000..fbab34bd4 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/customer_status.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + CANCELED = 3 + SUSPENDED = 4 + CLOSED = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/customizer_attribute_status.py b/google/ads/googleads/v15/enums/types/customizer_attribute_status.py new file mode 100644 index 000000000..874345f77 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/customizer_attribute_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/customizer_attribute_type.py b/google/ads/googleads/v15/enums/types/customizer_attribute_type.py new file mode 100644 index 000000000..64b96da66 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/customizer_attribute_type.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + TEXT = 2 + NUMBER = 3 + PRICE = 4 + PERCENT = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/customizer_value_status.py b/google/ads/googleads/v15/enums/types/customizer_value_status.py new file mode 100644 index 000000000..183a8f904 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/customizer_value_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/data_driven_model_status.py b/google/ads/googleads/v15/enums/types/data_driven_model_status.py new file mode 100644 index 000000000..ac2c8db16 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/data_driven_model_status.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + AVAILABLE = 2 + STALE = 3 + EXPIRED = 4 + NEVER_GENERATED = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/day_of_week.py b/google/ads/googleads/v15/enums/types/day_of_week.py new file mode 100644 index 000000000..b6078869a --- /dev/null +++ b/google/ads/googleads/v15/enums/types/day_of_week.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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".""" + 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/v15/enums/types/device.py b/google/ads/googleads/v15/enums/types/device.py new file mode 100644 index 000000000..7bbfa14c9 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/device.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/display_ad_format_setting.py b/google/ads/googleads/v15/enums/types/display_ad_format_setting.py new file mode 100644 index 000000000..97c25aaac --- /dev/null +++ b/google/ads/googleads/v15/enums/types/display_ad_format_setting.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "DisplayAdFormatSettingEnum", + }, +) + + +class DisplayAdFormatSettingEnum(proto.Message): + r"""Container for display ad format settings.""" + + class DisplayAdFormatSetting(proto.Enum): + r"""Enumerates display ad format settings.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ALL_FORMATS = 2 + NON_NATIVE = 3 + NATIVE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/display_upload_product_type.py b/google/ads/googleads/v15/enums/types/display_upload_product_type.py new file mode 100644 index 000000000..167650b3f --- /dev/null +++ b/google/ads/googleads/v15/enums/types/display_upload_product_type.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/distance_bucket.py b/google/ads/googleads/v15/enums/types/distance_bucket.py new file mode 100644 index 000000000..77c95cc6d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/distance_bucket.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/dsa_page_feed_criterion_field.py b/google/ads/googleads/v15/enums/types/dsa_page_feed_criterion_field.py new file mode 100644 index 000000000..1be474e75 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/dsa_page_feed_criterion_field.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "DsaPageFeedCriterionFieldEnum", + }, +) + + +class DsaPageFeedCriterionFieldEnum(proto.Message): + r"""Values for Dynamic Search Ad Page Feed criterion fields.""" + + class DsaPageFeedCriterionField(proto.Enum): + r"""Possible values for Dynamic Search Ad Page Feed criterion + fields. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + PAGE_URL = 2 + LABEL = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/education_placeholder_field.py b/google/ads/googleads/v15/enums/types/education_placeholder_field.py new file mode 100644 index 000000000..74cdccdb0 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/education_placeholder_field.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "EducationPlaceholderFieldEnum", + }, +) + + +class EducationPlaceholderFieldEnum(proto.Message): + r"""Values for Education placeholder fields. + For more information about dynamic remarketing feeds, see + https://support.google.com/google-ads/answer/6053288. + + """ + + class EducationPlaceholderField(proto.Enum): + r"""Possible values for Education placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PROGRAM_ID = 2 + LOCATION_ID = 3 + PROGRAM_NAME = 4 + AREA_OF_STUDY = 5 + PROGRAM_DESCRIPTION = 6 + SCHOOL_NAME = 7 + ADDRESS = 8 + THUMBNAIL_IMAGE_URL = 9 + ALTERNATIVE_THUMBNAIL_IMAGE_URL = 10 + FINAL_URLS = 11 + FINAL_MOBILE_URLS = 12 + TRACKING_URL = 13 + CONTEXTUAL_KEYWORDS = 14 + ANDROID_APP_LINK = 15 + SIMILAR_PROGRAM_IDS = 16 + IOS_APP_LINK = 17 + IOS_APP_STORE_ID = 18 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/experiment_metric.py b/google/ads/googleads/v15/enums/types/experiment_metric.py new file mode 100644 index 000000000..88c9cf166 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/experiment_metric.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/experiment_metric_direction.py b/google/ads/googleads/v15/enums/types/experiment_metric_direction.py new file mode 100644 index 000000000..5bef0681c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/experiment_metric_direction.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/experiment_status.py b/google/ads/googleads/v15/enums/types/experiment_status.py new file mode 100644 index 000000000..89bed4fb4 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/experiment_status.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "ExperimentStatusEnum", + }, +) + + +class ExperimentStatusEnum(proto.Message): + r"""Container for enum describing the experiment status.""" + + class ExperimentStatus(proto.Enum): + r"""The status of the experiment.""" + 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/v15/enums/types/experiment_type.py b/google/ads/googleads/v15/enums/types/experiment_type.py new file mode 100644 index 000000000..c4f670265 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/experiment_type.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/extension_setting_device.py b/google/ads/googleads/v15/enums/types/extension_setting_device.py new file mode 100644 index 000000000..ebf2a0526 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/extension_setting_device.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "ExtensionSettingDeviceEnum", + }, +) + + +class ExtensionSettingDeviceEnum(proto.Message): + r"""Container for enum describing extension setting device types.""" + + class ExtensionSettingDevice(proto.Enum): + r"""Possible device types for an extension setting.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + MOBILE = 2 + DESKTOP = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/extension_type.py b/google/ads/googleads/v15/enums/types/extension_type.py new file mode 100644 index 000000000..553701089 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/extension_type.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "ExtensionTypeEnum", + }, +) + + +class ExtensionTypeEnum(proto.Message): + r"""Container for enum describing possible data types for an + extension in an extension setting. + + """ + + class ExtensionType(proto.Enum): + r"""Possible data types for an extension in an extension setting.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + NONE = 2 + APP = 3 + CALL = 4 + CALLOUT = 5 + MESSAGE = 6 + PRICE = 7 + PROMOTION = 8 + SITELINK = 10 + STRUCTURED_SNIPPET = 11 + LOCATION = 12 + AFFILIATE_LOCATION = 13 + HOTEL_CALLOUT = 15 + IMAGE = 16 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/external_conversion_source.py b/google/ads/googleads/v15/enums/types/external_conversion_source.py new file mode 100644 index 000000000..ba6472d2b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/external_conversion_source.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/feed_attribute_type.py b/google/ads/googleads/v15/enums/types/feed_attribute_type.py new file mode 100644 index 000000000..8359b82fe --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_attribute_type.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedAttributeTypeEnum", + }, +) + + +class FeedAttributeTypeEnum(proto.Message): + r"""Container for enum describing possible data types for a feed + attribute. + + """ + + class FeedAttributeType(proto.Enum): + r"""Possible data types for a feed attribute.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + INT64 = 2 + DOUBLE = 3 + STRING = 4 + BOOLEAN = 5 + URL = 6 + DATE_TIME = 7 + INT64_LIST = 8 + DOUBLE_LIST = 9 + STRING_LIST = 10 + BOOLEAN_LIST = 11 + URL_LIST = 12 + DATE_TIME_LIST = 13 + PRICE = 14 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_item_quality_approval_status.py b/google/ads/googleads/v15/enums/types/feed_item_quality_approval_status.py new file mode 100644 index 000000000..3eeba312c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_item_quality_approval_status.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedItemQualityApprovalStatusEnum", + }, +) + + +class FeedItemQualityApprovalStatusEnum(proto.Message): + r"""Container for enum describing possible quality evaluation + approval statuses of a feed item. + + """ + + class FeedItemQualityApprovalStatus(proto.Enum): + r"""The possible quality evaluation approval statuses of a feed + item. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + APPROVED = 2 + DISAPPROVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_item_quality_disapproval_reason.py b/google/ads/googleads/v15/enums/types/feed_item_quality_disapproval_reason.py new file mode 100644 index 000000000..bcea0763f --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_item_quality_disapproval_reason.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedItemQualityDisapprovalReasonEnum", + }, +) + + +class FeedItemQualityDisapprovalReasonEnum(proto.Message): + r"""Container for enum describing possible quality evaluation + disapproval reasons of a feed item. + + """ + + class FeedItemQualityDisapprovalReason(proto.Enum): + r"""The possible quality evaluation disapproval reasons of a feed + item. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + PRICE_TABLE_REPETITIVE_HEADERS = 2 + PRICE_TABLE_REPETITIVE_DESCRIPTION = 3 + PRICE_TABLE_INCONSISTENT_ROWS = 4 + PRICE_DESCRIPTION_HAS_PRICE_QUALIFIERS = 5 + PRICE_UNSUPPORTED_LANGUAGE = 6 + PRICE_TABLE_ROW_HEADER_TABLE_TYPE_MISMATCH = 7 + PRICE_TABLE_ROW_HEADER_HAS_PROMOTIONAL_TEXT = 8 + PRICE_TABLE_ROW_DESCRIPTION_NOT_RELEVANT = 9 + PRICE_TABLE_ROW_DESCRIPTION_HAS_PROMOTIONAL_TEXT = 10 + PRICE_TABLE_ROW_HEADER_DESCRIPTION_REPETITIVE = 11 + PRICE_TABLE_ROW_UNRATEABLE = 12 + PRICE_TABLE_ROW_PRICE_INVALID = 13 + PRICE_TABLE_ROW_URL_INVALID = 14 + PRICE_HEADER_OR_DESCRIPTION_HAS_PRICE = 15 + STRUCTURED_SNIPPETS_HEADER_POLICY_VIOLATED = 16 + STRUCTURED_SNIPPETS_REPEATED_VALUES = 17 + STRUCTURED_SNIPPETS_EDITORIAL_GUIDELINES = 18 + STRUCTURED_SNIPPETS_HAS_PROMOTIONAL_TEXT = 19 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_item_set_status.py b/google/ads/googleads/v15/enums/types/feed_item_set_status.py new file mode 100644 index 000000000..9bd84eff7 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_item_set_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedItemSetStatusEnum", + }, +) + + +class FeedItemSetStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a feed + item set. + + """ + + class FeedItemSetStatus(proto.Enum): + r"""Possible statuses of a feed item set.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_item_set_string_filter_type.py b/google/ads/googleads/v15/enums/types/feed_item_set_string_filter_type.py new file mode 100644 index 000000000..39792b2ea --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_item_set_string_filter_type.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedItemSetStringFilterTypeEnum", + }, +) + + +class FeedItemSetStringFilterTypeEnum(proto.Message): + r"""The type of string matching to be used for a dynamic + FeedItemSet filter. + + """ + + class FeedItemSetStringFilterType(proto.Enum): + r"""describe the possible types for a FeedItemSetStringFilter.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + EXACT = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_item_status.py b/google/ads/googleads/v15/enums/types/feed_item_status.py new file mode 100644 index 000000000..238b405a8 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_item_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedItemStatusEnum", + }, +) + + +class FeedItemStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a feed + item. + + """ + + class FeedItemStatus(proto.Enum): + r"""Possible statuses of a feed item.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_item_target_device.py b/google/ads/googleads/v15/enums/types/feed_item_target_device.py new file mode 100644 index 000000000..6ff4dadd9 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_item_target_device.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedItemTargetDeviceEnum", + }, +) + + +class FeedItemTargetDeviceEnum(proto.Message): + r"""Container for enum describing possible data types for a feed + item target device. + + """ + + class FeedItemTargetDevice(proto.Enum): + r"""Possible data types for a feed item target device.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + MOBILE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_item_target_status.py b/google/ads/googleads/v15/enums/types/feed_item_target_status.py new file mode 100644 index 000000000..504a5239b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_item_target_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedItemTargetStatusEnum", + }, +) + + +class FeedItemTargetStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a feed + item target. + + """ + + class FeedItemTargetStatus(proto.Enum): + r"""Possible statuses of a feed item target.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_item_target_type.py b/google/ads/googleads/v15/enums/types/feed_item_target_type.py new file mode 100644 index 000000000..8a0014403 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_item_target_type.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedItemTargetTypeEnum", + }, +) + + +class FeedItemTargetTypeEnum(proto.Message): + r"""Container for enum describing possible types of a feed item + target. + + """ + + class FeedItemTargetType(proto.Enum): + r"""Possible type of a feed item target.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGN = 2 + AD_GROUP = 3 + CRITERION = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_item_validation_status.py b/google/ads/googleads/v15/enums/types/feed_item_validation_status.py new file mode 100644 index 000000000..aa4be05ae --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_item_validation_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedItemValidationStatusEnum", + }, +) + + +class FeedItemValidationStatusEnum(proto.Message): + r"""Container for enum describing possible validation statuses of + a feed item. + + """ + + class FeedItemValidationStatus(proto.Enum): + r"""The possible validation statuses of a feed item.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + INVALID = 3 + VALID = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_link_status.py b/google/ads/googleads/v15/enums/types/feed_link_status.py new file mode 100644 index 000000000..8d7649bf7 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_link_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedLinkStatusEnum", + }, +) + + +class FeedLinkStatusEnum(proto.Message): + r"""Container for an enum describing possible statuses of a feed + link. + + """ + + class FeedLinkStatus(proto.Enum): + r"""Possible statuses of a feed link.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_mapping_criterion_type.py b/google/ads/googleads/v15/enums/types/feed_mapping_criterion_type.py new file mode 100644 index 000000000..bed03e843 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_mapping_criterion_type.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedMappingCriterionTypeEnum", + }, +) + + +class FeedMappingCriterionTypeEnum(proto.Message): + r"""Container for enum describing possible criterion types for a + feed mapping. + + """ + + class FeedMappingCriterionType(proto.Enum): + r"""Possible placeholder types for a feed mapping.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + LOCATION_EXTENSION_TARGETING = 4 + DSA_PAGE_FEED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_mapping_status.py b/google/ads/googleads/v15/enums/types/feed_mapping_status.py new file mode 100644 index 000000000..968c25d10 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_mapping_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedMappingStatusEnum", + }, +) + + +class FeedMappingStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a feed + mapping. + + """ + + class FeedMappingStatus(proto.Enum): + r"""Possible statuses of a feed mapping.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_origin.py b/google/ads/googleads/v15/enums/types/feed_origin.py new file mode 100644 index 000000000..d625c22ce --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_origin.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedOriginEnum", + }, +) + + +class FeedOriginEnum(proto.Message): + r"""Container for enum describing possible values for a feed + origin. + + """ + + class FeedOrigin(proto.Enum): + r"""Possible values for a feed origin.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + USER = 2 + GOOGLE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/feed_status.py b/google/ads/googleads/v15/enums/types/feed_status.py new file mode 100644 index 000000000..a0f2e91f3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/feed_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FeedStatusEnum", + }, +) + + +class FeedStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of a feed.""" + + class FeedStatus(proto.Enum): + r"""Possible statuses of a feed.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/flight_placeholder_field.py b/google/ads/googleads/v15/enums/types/flight_placeholder_field.py new file mode 100644 index 000000000..64f7b6cb0 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/flight_placeholder_field.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "FlightPlaceholderFieldEnum", + }, +) + + +class FlightPlaceholderFieldEnum(proto.Message): + r"""Values for Flight placeholder fields. + For more information about dynamic remarketing feeds, see + https://support.google.com/google-ads/answer/6053288. + + """ + + class FlightPlaceholderField(proto.Enum): + r"""Possible values for Flight placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + DESTINATION_ID = 2 + ORIGIN_ID = 3 + FLIGHT_DESCRIPTION = 4 + ORIGIN_NAME = 5 + DESTINATION_NAME = 6 + FLIGHT_PRICE = 7 + FORMATTED_PRICE = 8 + FLIGHT_SALE_PRICE = 9 + FORMATTED_SALE_PRICE = 10 + IMAGE_URL = 11 + FINAL_URLS = 12 + FINAL_MOBILE_URLS = 13 + TRACKING_URL = 14 + ANDROID_APP_LINK = 15 + SIMILAR_DESTINATION_IDS = 16 + IOS_APP_LINK = 17 + IOS_APP_STORE_ID = 18 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/frequency_cap_event_type.py b/google/ads/googleads/v15/enums/types/frequency_cap_event_type.py new file mode 100644 index 000000000..0a6dd23de --- /dev/null +++ b/google/ads/googleads/v15/enums/types/frequency_cap_event_type.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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). + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + IMPRESSION = 2 + VIDEO_VIEW = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/frequency_cap_level.py b/google/ads/googleads/v15/enums/types/frequency_cap_level.py new file mode 100644 index 000000000..be5a69954 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/frequency_cap_level.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + AD_GROUP_AD = 2 + AD_GROUP = 3 + CAMPAIGN = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/frequency_cap_time_unit.py b/google/ads/googleads/v15/enums/types/frequency_cap_time_unit.py new file mode 100644 index 000000000..8a065d130 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/frequency_cap_time_unit.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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).""" + UNSPECIFIED = 0 + UNKNOWN = 1 + DAY = 2 + WEEK = 3 + MONTH = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/gender_type.py b/google/ads/googleads/v15/enums/types/gender_type.py new file mode 100644 index 000000000..48abeb595 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/gender_type.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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).""" + UNSPECIFIED = 0 + UNKNOWN = 1 + MALE = 10 + FEMALE = 11 + UNDETERMINED = 20 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/geo_target_constant_status.py b/google/ads/googleads/v15/enums/types/geo_target_constant_status.py new file mode 100644 index 000000000..85c84a4f2 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/geo_target_constant_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVAL_PLANNED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/geo_targeting_restriction.py b/google/ads/googleads/v15/enums/types/geo_targeting_restriction.py new file mode 100644 index 000000000..de8f2aa88 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/geo_targeting_restriction.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "GeoTargetingRestrictionEnum", + }, +) + + +class GeoTargetingRestrictionEnum(proto.Message): + r"""Message describing feed item geo targeting restriction.""" + + class GeoTargetingRestriction(proto.Enum): + r"""A restriction used to determine if the request context's + geo should be matched. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + LOCATION_OF_PRESENCE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/geo_targeting_type.py b/google/ads/googleads/v15/enums/types/geo_targeting_type.py new file mode 100644 index 000000000..ddae95827 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/geo_targeting_type.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + AREA_OF_INTEREST = 2 + LOCATION_OF_PRESENCE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/goal_config_level.py b/google/ads/googleads/v15/enums/types/goal_config_level.py new file mode 100644 index 000000000..0083b6a41 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/goal_config_level.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER = 2 + CAMPAIGN = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/google_ads_field_category.py b/google/ads/googleads/v15/enums/types/google_ads_field_category.py new file mode 100644 index 000000000..0066170bd --- /dev/null +++ b/google/ads/googleads/v15/enums/types/google_ads_field_category.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + RESOURCE = 2 + ATTRIBUTE = 3 + SEGMENT = 5 + METRIC = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/google_ads_field_data_type.py b/google/ads/googleads/v15/enums/types/google_ads_field_data_type.py new file mode 100644 index 000000000..7f3e4cc7c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/google_ads_field_data_type.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/google_voice_call_status.py b/google/ads/googleads/v15/enums/types/google_voice_call_status.py new file mode 100644 index 000000000..7eedaba17 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/google_voice_call_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + MISSED = 2 + RECEIVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/hotel_asset_suggestion_status.py b/google/ads/googleads/v15/enums/types/hotel_asset_suggestion_status.py new file mode 100644 index 000000000..7f520e377 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/hotel_asset_suggestion_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/hotel_date_selection_type.py b/google/ads/googleads/v15/enums/types/hotel_date_selection_type.py new file mode 100644 index 000000000..468bf3d90 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/hotel_date_selection_type.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + DEFAULT_SELECTION = 50 + USER_SELECTED = 51 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/hotel_placeholder_field.py b/google/ads/googleads/v15/enums/types/hotel_placeholder_field.py new file mode 100644 index 000000000..d5da45169 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/hotel_placeholder_field.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "HotelPlaceholderFieldEnum", + }, +) + + +class HotelPlaceholderFieldEnum(proto.Message): + r"""Values for Hotel placeholder fields. + For more information about dynamic remarketing feeds, see + https://support.google.com/google-ads/answer/6053288. + + """ + + class HotelPlaceholderField(proto.Enum): + r"""Possible values for Hotel placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PROPERTY_ID = 2 + PROPERTY_NAME = 3 + DESTINATION_NAME = 4 + DESCRIPTION = 5 + ADDRESS = 6 + PRICE = 7 + FORMATTED_PRICE = 8 + SALE_PRICE = 9 + FORMATTED_SALE_PRICE = 10 + IMAGE_URL = 11 + CATEGORY = 12 + STAR_RATING = 13 + CONTEXTUAL_KEYWORDS = 14 + FINAL_URLS = 15 + FINAL_MOBILE_URLS = 16 + TRACKING_URL = 17 + ANDROID_APP_LINK = 18 + SIMILAR_PROPERTY_IDS = 19 + IOS_APP_LINK = 20 + IOS_APP_STORE_ID = 21 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/hotel_price_bucket.py b/google/ads/googleads/v15/enums/types/hotel_price_bucket.py new file mode 100644 index 000000000..1c24bc9f0 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/hotel_price_bucket.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/hotel_rate_type.py b/google/ads/googleads/v15/enums/types/hotel_rate_type.py new file mode 100644 index 000000000..bbec1f2c2 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/hotel_rate_type.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/hotel_reconciliation_status.py b/google/ads/googleads/v15/enums/types/hotel_reconciliation_status.py new file mode 100644 index 000000000..50349b22e --- /dev/null +++ b/google/ads/googleads/v15/enums/types/hotel_reconciliation_status.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "HotelReconciliationStatusEnum", + }, +) + + +class HotelReconciliationStatusEnum(proto.Message): + r"""Container for HotelReconciliationStatus.""" + + class HotelReconciliationStatus(proto.Enum): + r"""Status of the hotel booking reconciliation.""" + 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/v15/enums/types/image_placeholder_field.py b/google/ads/googleads/v15/enums/types/image_placeholder_field.py new file mode 100644 index 000000000..26f637307 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/image_placeholder_field.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "ImagePlaceholderFieldEnum", + }, +) + + +class ImagePlaceholderFieldEnum(proto.Message): + r"""Values for Advertiser Provided Image placeholder fields.""" + + class ImagePlaceholderField(proto.Enum): + r"""Possible values for Advertiser Provided Image placeholder + fields. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + ASSET_ID = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/income_range_type.py b/google/ads/googleads/v15/enums/types/income_range_type.py new file mode 100644 index 000000000..0385c8121 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/income_range_type.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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%). + """ + 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/v15/enums/types/interaction_event_type.py b/google/ads/googleads/v15/enums/types/interaction_event_type.py new file mode 100644 index 000000000..058a047f4 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/interaction_event_type.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + CLICK = 2 + ENGAGEMENT = 3 + VIDEO_VIEW = 4 + NONE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/interaction_type.py b/google/ads/googleads/v15/enums/types/interaction_type.py new file mode 100644 index 000000000..6172b954e --- /dev/null +++ b/google/ads/googleads/v15/enums/types/interaction_type.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "InteractionTypeEnum", + }, +) + + +class InteractionTypeEnum(proto.Message): + r"""Container for enum describing possible interaction types.""" + + class InteractionType(proto.Enum): + r"""Enum describing possible interaction types.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CALLS = 8000 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/invoice_type.py b/google/ads/googleads/v15/enums/types/invoice_type.py new file mode 100644 index 000000000..69d0e91e1 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/invoice_type.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CREDIT_MEMO = 2 + INVOICE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/job_placeholder_field.py b/google/ads/googleads/v15/enums/types/job_placeholder_field.py new file mode 100644 index 000000000..99219d66e --- /dev/null +++ b/google/ads/googleads/v15/enums/types/job_placeholder_field.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "JobPlaceholderFieldEnum", + }, +) + + +class JobPlaceholderFieldEnum(proto.Message): + r"""Values for Job placeholder fields. + For more information about dynamic remarketing feeds, see + https://support.google.com/google-ads/answer/6053288. + + """ + + class JobPlaceholderField(proto.Enum): + r"""Possible values for Job placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + JOB_ID = 2 + LOCATION_ID = 3 + TITLE = 4 + SUBTITLE = 5 + DESCRIPTION = 6 + IMAGE_URL = 7 + CATEGORY = 8 + CONTEXTUAL_KEYWORDS = 9 + ADDRESS = 10 + SALARY = 11 + FINAL_URLS = 12 + FINAL_MOBILE_URLS = 14 + TRACKING_URL = 15 + ANDROID_APP_LINK = 16 + SIMILAR_JOB_IDS = 17 + IOS_APP_LINK = 18 + IOS_APP_STORE_ID = 19 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/keyword_match_type.py b/google/ads/googleads/v15/enums/types/keyword_match_type.py new file mode 100644 index 000000000..335507ac2 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/keyword_match_type.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "KeywordMatchTypeEnum", + }, +) + + +class KeywordMatchTypeEnum(proto.Message): + r"""Message describing Keyword match types.""" + + class KeywordMatchType(proto.Enum): + r"""Possible Keyword match types.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + EXACT = 2 + PHRASE = 3 + BROAD = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/keyword_plan_aggregate_metric_type.py b/google/ads/googleads/v15/enums/types/keyword_plan_aggregate_metric_type.py new file mode 100644 index 000000000..abe6026d8 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/keyword_plan_aggregate_metric_type.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "KeywordPlanAggregateMetricTypeEnum", + }, +) + + +class KeywordPlanAggregateMetricTypeEnum(proto.Message): + r"""The enumeration of keyword plan aggregate metric types.""" + + class KeywordPlanAggregateMetricType(proto.Enum): + r"""Aggregate fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + DEVICE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/keyword_plan_competition_level.py b/google/ads/googleads/v15/enums/types/keyword_plan_competition_level.py new file mode 100644 index 000000000..61a611741 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/keyword_plan_competition_level.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + LOW = 2 + MEDIUM = 3 + HIGH = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/keyword_plan_concept_group_type.py b/google/ads/googleads/v15/enums/types/keyword_plan_concept_group_type.py new file mode 100644 index 000000000..9096fe35e --- /dev/null +++ b/google/ads/googleads/v15/enums/types/keyword_plan_concept_group_type.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + BRAND = 2 + OTHER_BRANDS = 3 + NON_BRAND = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/keyword_plan_forecast_interval.py b/google/ads/googleads/v15/enums/types/keyword_plan_forecast_interval.py new file mode 100644 index 000000000..d5f92e406 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/keyword_plan_forecast_interval.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "KeywordPlanForecastIntervalEnum", + }, +) + + +class KeywordPlanForecastIntervalEnum(proto.Message): + r"""Container for enumeration of forecast intervals.""" + + class KeywordPlanForecastInterval(proto.Enum): + r"""Forecast intervals.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + NEXT_WEEK = 3 + NEXT_MONTH = 4 + NEXT_QUARTER = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/keyword_plan_keyword_annotation.py b/google/ads/googleads/v15/enums/types/keyword_plan_keyword_annotation.py new file mode 100644 index 000000000..6c829d5ed --- /dev/null +++ b/google/ads/googleads/v15/enums/types/keyword_plan_keyword_annotation.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + KEYWORD_CONCEPT = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/keyword_plan_network.py b/google/ads/googleads/v15/enums/types/keyword_plan_network.py new file mode 100644 index 000000000..1b73586c9 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/keyword_plan_network.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + GOOGLE_SEARCH = 2 + GOOGLE_SEARCH_AND_PARTNERS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/label_status.py b/google/ads/googleads/v15/enums/types/label_status.py new file mode 100644 index 000000000..6b7ae625f --- /dev/null +++ b/google/ads/googleads/v15/enums/types/label_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/lead_form_call_to_action_type.py b/google/ads/googleads/v15/enums/types/lead_form_call_to_action_type.py new file mode 100644 index 000000000..48eaa95e8 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/lead_form_call_to_action_type.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/lead_form_desired_intent.py b/google/ads/googleads/v15/enums/types/lead_form_desired_intent.py new file mode 100644 index 000000000..e9504cc20 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/lead_form_desired_intent.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + LOW_INTENT = 2 + HIGH_INTENT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/lead_form_field_user_input_type.py b/google/ads/googleads/v15/enums/types/lead_form_field_user_input_type.py new file mode 100644 index 000000000..50981aaf6 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/lead_form_field_user_input_type.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/lead_form_post_submit_call_to_action_type.py b/google/ads/googleads/v15/enums/types/lead_form_post_submit_call_to_action_type.py new file mode 100644 index 000000000..9d738708d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/lead_form_post_submit_call_to_action_type.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/legacy_app_install_ad_app_store.py b/google/ads/googleads/v15/enums/types/legacy_app_install_ad_app_store.py new file mode 100644 index 000000000..0197d0574 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/legacy_app_install_ad_app_store.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/linked_account_type.py b/google/ads/googleads/v15/enums/types/linked_account_type.py new file mode 100644 index 000000000..a6ca44aa3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/linked_account_type.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + THIRD_PARTY_APP_ANALYTICS = 2 + DATA_PARTNER = 3 + GOOGLE_ADS = 4 + ADVERTISING_PARTNER = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/linked_product_type.py b/google/ads/googleads/v15/enums/types/linked_product_type.py new file mode 100644 index 000000000..395b821f2 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/linked_product_type.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + DATA_PARTNER = 2 + GOOGLE_ADS = 3 + HOTEL_CENTER = 7 + MERCHANT_CENTER = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/listing_group_filter_custom_attribute_index.py b/google/ads/googleads/v15/enums/types/listing_group_filter_custom_attribute_index.py new file mode 100644 index 000000000..b8a314390 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/listing_group_filter_custom_attribute_index.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/listing_group_filter_listing_source.py b/google/ads/googleads/v15/enums/types/listing_group_filter_listing_source.py new file mode 100644 index 000000000..e35ebb4b1 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/listing_group_filter_listing_source.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + SHOPPING = 2 + WEBPAGE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/listing_group_filter_product_category_level.py b/google/ads/googleads/v15/enums/types/listing_group_filter_product_category_level.py new file mode 100644 index 000000000..76b2a44dd --- /dev/null +++ b/google/ads/googleads/v15/enums/types/listing_group_filter_product_category_level.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/listing_group_filter_product_channel.py b/google/ads/googleads/v15/enums/types/listing_group_filter_product_channel.py new file mode 100644 index 000000000..eda6ec4c2 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/listing_group_filter_product_channel.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ONLINE = 2 + LOCAL = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/listing_group_filter_product_condition.py b/google/ads/googleads/v15/enums/types/listing_group_filter_product_condition.py new file mode 100644 index 000000000..fd40c60be --- /dev/null +++ b/google/ads/googleads/v15/enums/types/listing_group_filter_product_condition.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + NEW = 2 + REFURBISHED = 3 + USED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/listing_group_filter_product_type_level.py b/google/ads/googleads/v15/enums/types/listing_group_filter_product_type_level.py new file mode 100644 index 000000000..ff790ad0b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/listing_group_filter_product_type_level.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/listing_group_filter_type_enum.py b/google/ads/googleads/v15/enums/types/listing_group_filter_type_enum.py new file mode 100644 index 000000000..4a610a15b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/listing_group_filter_type_enum.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + SUBDIVISION = 2 + UNIT_INCLUDED = 3 + UNIT_EXCLUDED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/listing_group_type.py b/google/ads/googleads/v15/enums/types/listing_group_type.py new file mode 100644 index 000000000..da6d80c97 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/listing_group_type.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + SUBDIVISION = 2 + UNIT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/listing_type.py b/google/ads/googleads/v15/enums/types/listing_type.py new file mode 100644 index 000000000..816a27ad8 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/listing_type.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "ListingTypeEnum", + }, +) + + +class ListingTypeEnum(proto.Message): + r"""Container for enum describing possible listing types.""" + + class ListingType(proto.Enum): + r"""Possible listing types.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + VEHICLES = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/local_placeholder_field.py b/google/ads/googleads/v15/enums/types/local_placeholder_field.py new file mode 100644 index 000000000..f922d16c2 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/local_placeholder_field.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "LocalPlaceholderFieldEnum", + }, +) + + +class LocalPlaceholderFieldEnum(proto.Message): + r"""Values for Local placeholder fields. + For more information about dynamic remarketing feeds, see + https://support.google.com/google-ads/answer/6053288. + + """ + + class LocalPlaceholderField(proto.Enum): + r"""Possible values for Local placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + DEAL_ID = 2 + DEAL_NAME = 3 + SUBTITLE = 4 + DESCRIPTION = 5 + PRICE = 6 + FORMATTED_PRICE = 7 + SALE_PRICE = 8 + FORMATTED_SALE_PRICE = 9 + IMAGE_URL = 10 + ADDRESS = 11 + CATEGORY = 12 + CONTEXTUAL_KEYWORDS = 13 + FINAL_URLS = 14 + FINAL_MOBILE_URLS = 15 + TRACKING_URL = 16 + ANDROID_APP_LINK = 17 + SIMILAR_DEAL_IDS = 18 + IOS_APP_LINK = 19 + IOS_APP_STORE_ID = 20 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/local_services_conversation_type.py b/google/ads/googleads/v15/enums/types/local_services_conversation_type.py new file mode 100644 index 000000000..af32df96c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/local_services_conversation_type.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + EMAIL = 2 + MESSAGE = 3 + PHONE_CALL = 4 + SMS = 5 + BOOKING = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/local_services_insurance_rejection_reason.py b/google/ads/googleads/v15/enums/types/local_services_insurance_rejection_reason.py new file mode 100644 index 000000000..a9ff396ec --- /dev/null +++ b/google/ads/googleads/v15/enums/types/local_services_insurance_rejection_reason.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/local_services_lead_status.py b/google/ads/googleads/v15/enums/types/local_services_lead_status.py new file mode 100644 index 000000000..ea68a87ae --- /dev/null +++ b/google/ads/googleads/v15/enums/types/local_services_lead_status.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "LocalServicesLeadStatusEnum", + }, +) + + +class LocalServicesLeadStatusEnum(proto.Message): + r"""Container for enum describing possible statuses of lead.""" + + class LeadStatus(proto.Enum): + r"""Possible statuses of lead.""" + 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/v15/enums/types/local_services_lead_type.py b/google/ads/googleads/v15/enums/types/local_services_lead_type.py new file mode 100644 index 000000000..b0aa792fc --- /dev/null +++ b/google/ads/googleads/v15/enums/types/local_services_lead_type.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "LocalServicesLeadTypeEnum", + }, +) + + +class LocalServicesLeadTypeEnum(proto.Message): + r"""Container for enum describing possible types of lead.""" + + class LeadType(proto.Enum): + r"""Possible types of lead.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + MESSAGE = 2 + PHONE_CALL = 3 + BOOKING = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/local_services_license_rejection_reason.py b/google/ads/googleads/v15/enums/types/local_services_license_rejection_reason.py new file mode 100644 index 000000000..a888750e8 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/local_services_license_rejection_reason.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/local_services_participant_type.py b/google/ads/googleads/v15/enums/types/local_services_participant_type.py new file mode 100644 index 000000000..80f5e44ee --- /dev/null +++ b/google/ads/googleads/v15/enums/types/local_services_participant_type.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ADVERTISER = 2 + CONSUMER = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/local_services_verification_artifact_status.py b/google/ads/googleads/v15/enums/types/local_services_verification_artifact_status.py new file mode 100644 index 000000000..c732c3669 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/local_services_verification_artifact_status.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/local_services_verification_artifact_type.py b/google/ads/googleads/v15/enums/types/local_services_verification_artifact_type.py new file mode 100644 index 000000000..57191bcb9 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/local_services_verification_artifact_type.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + BACKGROUND_CHECK = 2 + INSURANCE = 3 + LICENSE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/local_services_verification_status.py b/google/ads/googleads/v15/enums/types/local_services_verification_status.py new file mode 100644 index 000000000..5eeff1a62 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/local_services_verification_status.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/location_extension_targeting_criterion_field.py b/google/ads/googleads/v15/enums/types/location_extension_targeting_criterion_field.py new file mode 100644 index 000000000..ab9b3b67d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/location_extension_targeting_criterion_field.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "LocationExtensionTargetingCriterionFieldEnum", + }, +) + + +class LocationExtensionTargetingCriterionFieldEnum(proto.Message): + r"""Values for Location Extension Targeting criterion fields.""" + + class LocationExtensionTargetingCriterionField(proto.Enum): + r"""Possible values for Location Extension Targeting criterion + fields. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + ADDRESS_LINE_1 = 2 + ADDRESS_LINE_2 = 3 + CITY = 4 + PROVINCE = 5 + POSTAL_CODE = 6 + COUNTRY_CODE = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/location_group_radius_units.py b/google/ads/googleads/v15/enums/types/location_group_radius_units.py new file mode 100644 index 000000000..0d4bc8e45 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/location_group_radius_units.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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) + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + METERS = 2 + MILES = 3 + MILLI_MILES = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/location_ownership_type.py b/google/ads/googleads/v15/enums/types/location_ownership_type.py new file mode 100644 index 000000000..b799e83ef --- /dev/null +++ b/google/ads/googleads/v15/enums/types/location_ownership_type.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + BUSINESS_OWNER = 2 + AFFILIATE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/location_placeholder_field.py b/google/ads/googleads/v15/enums/types/location_placeholder_field.py new file mode 100644 index 000000000..760871331 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/location_placeholder_field.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "LocationPlaceholderFieldEnum", + }, +) + + +class LocationPlaceholderFieldEnum(proto.Message): + r"""Values for Location placeholder fields.""" + + class LocationPlaceholderField(proto.Enum): + r"""Possible values for Location placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + BUSINESS_NAME = 2 + ADDRESS_LINE_1 = 3 + ADDRESS_LINE_2 = 4 + CITY = 5 + PROVINCE = 6 + POSTAL_CODE = 7 + COUNTRY_CODE = 8 + PHONE_NUMBER = 9 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/location_source_type.py b/google/ads/googleads/v15/enums/types/location_source_type.py new file mode 100644 index 000000000..3b2c647a6 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/location_source_type.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + GOOGLE_MY_BUSINESS = 2 + AFFILIATE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/location_string_filter_type.py b/google/ads/googleads/v15/enums/types/location_string_filter_type.py new file mode 100644 index 000000000..9a03e3736 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/location_string_filter_type.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + EXACT = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/lookalike_expansion_level.py b/google/ads/googleads/v15/enums/types/lookalike_expansion_level.py new file mode 100644 index 000000000..93b8a404f --- /dev/null +++ b/google/ads/googleads/v15/enums/types/lookalike_expansion_level.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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 + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + NARROW = 2 + BALANCED = 3 + BROAD = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/manager_link_status.py b/google/ads/googleads/v15/enums/types/manager_link_status.py new file mode 100644 index 000000000..e730d5565 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/manager_link_status.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/matching_function_context_type.py b/google/ads/googleads/v15/enums/types/matching_function_context_type.py new file mode 100644 index 000000000..01c5a3c0d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/matching_function_context_type.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "MatchingFunctionContextTypeEnum", + }, +) + + +class MatchingFunctionContextTypeEnum(proto.Message): + r"""Container for context types for an operand in a matching + function. + + """ + + class MatchingFunctionContextType(proto.Enum): + r"""Possible context types for an operand in a matching function.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + FEED_ITEM_ID = 2 + DEVICE_NAME = 3 + FEED_ITEM_SET_ID = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/matching_function_operator.py b/google/ads/googleads/v15/enums/types/matching_function_operator.py new file mode 100644 index 000000000..c6ee22a09 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/matching_function_operator.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "MatchingFunctionOperatorEnum", + }, +) + + +class MatchingFunctionOperatorEnum(proto.Message): + r"""Container for enum describing matching function operator.""" + + class MatchingFunctionOperator(proto.Enum): + r"""Possible operators in a matching function.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + IN = 2 + IDENTITY = 3 + EQUALS = 4 + AND = 5 + CONTAINS_ANY = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/media_type.py b/google/ads/googleads/v15/enums/types/media_type.py new file mode 100644 index 000000000..356706d11 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/media_type.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "MediaTypeEnum", + }, +) + + +class MediaTypeEnum(proto.Message): + r"""Container for enum describing the types of media.""" + + class MediaType(proto.Enum): + r"""The type of media.""" + 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/v15/enums/types/message_placeholder_field.py b/google/ads/googleads/v15/enums/types/message_placeholder_field.py new file mode 100644 index 000000000..3992e3933 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/message_placeholder_field.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "MessagePlaceholderFieldEnum", + }, +) + + +class MessagePlaceholderFieldEnum(proto.Message): + r"""Values for Message placeholder fields.""" + + class MessagePlaceholderField(proto.Enum): + r"""Possible values for Message placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + BUSINESS_NAME = 2 + COUNTRY_CODE = 3 + PHONE_NUMBER = 4 + MESSAGE_EXTENSION_TEXT = 5 + MESSAGE_TEXT = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/mime_type.py b/google/ads/googleads/v15/enums/types/mime_type.py new file mode 100644 index 000000000..7b3fc246b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/mime_type.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "MimeTypeEnum", + }, +) + + +class MimeTypeEnum(proto.Message): + r"""Container for enum describing the mime types.""" + + class MimeType(proto.Enum): + r"""The mime type""" + 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/v15/enums/types/minute_of_hour.py b/google/ads/googleads/v15/enums/types/minute_of_hour.py new file mode 100644 index 000000000..46c545f82 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/minute_of_hour.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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".""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ZERO = 2 + FIFTEEN = 3 + THIRTY = 4 + FORTY_FIVE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/mobile_app_vendor.py b/google/ads/googleads/v15/enums/types/mobile_app_vendor.py new file mode 100644 index 000000000..6fbc6db35 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/mobile_app_vendor.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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""" + UNSPECIFIED = 0 + UNKNOWN = 1 + APPLE_APP_STORE = 2 + GOOGLE_APP_STORE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/mobile_device_type.py b/google/ads/googleads/v15/enums/types/mobile_device_type.py new file mode 100644 index 000000000..7a9a2faea --- /dev/null +++ b/google/ads/googleads/v15/enums/types/mobile_device_type.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + MOBILE = 2 + TABLET = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/month_of_year.py b/google/ads/googleads/v15/enums/types/month_of_year.py new file mode 100644 index 000000000..c98c38195 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/month_of_year.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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".""" + 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/v15/enums/types/negative_geo_target_type.py b/google/ads/googleads/v15/enums/types/negative_geo_target_type.py new file mode 100644 index 000000000..adfd7e321 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/negative_geo_target_type.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PRESENCE_OR_INTEREST = 4 + PRESENCE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/offline_conversion_diagnostic_status_enum.py b/google/ads/googleads/v15/enums/types/offline_conversion_diagnostic_status_enum.py new file mode 100644 index 000000000..66c256d32 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/offline_conversion_diagnostic_status_enum.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/offline_event_upload_client_enum.py b/google/ads/googleads/v15/enums/types/offline_event_upload_client_enum.py new file mode 100644 index 000000000..bd724ea0d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/offline_event_upload_client_enum.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "OfflineEventUploadClientEnum", + }, +) + + +class OfflineEventUploadClientEnum(proto.Message): + r"""All possible clients for an offline upload event.""" + + class OfflineEventUploadClient(proto.Enum): + r"""Type of client.""" + 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/v15/enums/types/offline_user_data_job_failure_reason.py b/google/ads/googleads/v15/enums/types/offline_user_data_job_failure_reason.py new file mode 100644 index 000000000..05948b324 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/offline_user_data_job_failure_reason.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/offline_user_data_job_match_rate_range.py b/google/ads/googleads/v15/enums/types/offline_user_data_job_match_rate_range.py new file mode 100644 index 000000000..4d6a44e44 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/offline_user_data_job_match_rate_range.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/offline_user_data_job_status.py b/google/ads/googleads/v15/enums/types/offline_user_data_job_status.py new file mode 100644 index 000000000..797968414 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/offline_user_data_job_status.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PENDING = 2 + RUNNING = 3 + SUCCESS = 4 + FAILED = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/offline_user_data_job_type.py b/google/ads/googleads/v15/enums/types/offline_user_data_job_type.py new file mode 100644 index 000000000..6388d63ad --- /dev/null +++ b/google/ads/googleads/v15/enums/types/offline_user_data_job_type.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/operating_system_version_operator_type.py b/google/ads/googleads/v15/enums/types/operating_system_version_operator_type.py new file mode 100644 index 000000000..647495dc4 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/operating_system_version_operator_type.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + EQUALS_TO = 2 + GREATER_THAN_EQUALS_TO = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/optimization_goal_type.py b/google/ads/googleads/v15/enums/types/optimization_goal_type.py new file mode 100644 index 000000000..03af01c48 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/optimization_goal_type.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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""" + 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/v15/enums/types/parental_status_type.py b/google/ads/googleads/v15/enums/types/parental_status_type.py new file mode 100644 index 000000000..9b64b0f7b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/parental_status_type.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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).""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PARENT = 300 + NOT_A_PARENT = 301 + UNDETERMINED = 302 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/payment_mode.py b/google/ads/googleads/v15/enums/types/payment_mode.py new file mode 100644 index 000000000..62ef0eb7d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/payment_mode.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "PaymentModeEnum", + }, +) + + +class PaymentModeEnum(proto.Message): + r"""Container for enum describing possible payment modes.""" + + class PaymentMode(proto.Enum): + r"""Enum describing possible payment modes.""" + 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/v15/enums/types/performance_max_upgrade_status.py b/google/ads/googleads/v15/enums/types/performance_max_upgrade_status.py new file mode 100644 index 000000000..89b9564d8 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/performance_max_upgrade_status.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/placeholder_type.py b/google/ads/googleads/v15/enums/types/placeholder_type.py new file mode 100644 index 000000000..de3bdadcd --- /dev/null +++ b/google/ads/googleads/v15/enums/types/placeholder_type.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "PlaceholderTypeEnum", + }, +) + + +class PlaceholderTypeEnum(proto.Message): + r"""Container for enum describing possible placeholder types for + a feed mapping. + + """ + + class PlaceholderType(proto.Enum): + r"""Possible placeholder types for a feed mapping.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + SITELINK = 2 + CALL = 3 + APP = 4 + LOCATION = 5 + AFFILIATE_LOCATION = 6 + CALLOUT = 7 + STRUCTURED_SNIPPET = 8 + MESSAGE = 9 + PRICE = 10 + PROMOTION = 11 + AD_CUSTOMIZER = 12 + DYNAMIC_EDUCATION = 13 + DYNAMIC_FLIGHT = 14 + DYNAMIC_CUSTOM = 15 + DYNAMIC_HOTEL = 16 + DYNAMIC_REAL_ESTATE = 17 + DYNAMIC_TRAVEL = 18 + DYNAMIC_LOCAL = 19 + DYNAMIC_JOB = 20 + IMAGE = 21 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/placement_type.py b/google/ads/googleads/v15/enums/types/placement_type.py new file mode 100644 index 000000000..58afbf5ab --- /dev/null +++ b/google/ads/googleads/v15/enums/types/placement_type.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/policy_approval_status.py b/google/ads/googleads/v15/enums/types/policy_approval_status.py new file mode 100644 index 000000000..534fceb69 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/policy_approval_status.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/policy_review_status.py b/google/ads/googleads/v15/enums/types/policy_review_status.py new file mode 100644 index 000000000..de58b1269 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/policy_review_status.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/policy_topic_entry_type.py b/google/ads/googleads/v15/enums/types/policy_topic_entry_type.py new file mode 100644 index 000000000..03e55dac5 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/policy_topic_entry_type.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/policy_topic_evidence_destination_mismatch_url_type.py b/google/ads/googleads/v15/enums/types/policy_topic_evidence_destination_mismatch_url_type.py new file mode 100644 index 000000000..994c648b3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/policy_topic_evidence_destination_mismatch_url_type.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/policy_topic_evidence_destination_not_working_device.py b/google/ads/googleads/v15/enums/types/policy_topic_evidence_destination_not_working_device.py new file mode 100644 index 000000000..6a385111e --- /dev/null +++ b/google/ads/googleads/v15/enums/types/policy_topic_evidence_destination_not_working_device.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + DESKTOP = 2 + ANDROID = 3 + IOS = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/policy_topic_evidence_destination_not_working_dns_error_type.py b/google/ads/googleads/v15/enums/types/policy_topic_evidence_destination_not_working_dns_error_type.py new file mode 100644 index 000000000..e448777b9 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/policy_topic_evidence_destination_not_working_dns_error_type.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + HOSTNAME_NOT_FOUND = 2 + GOOGLE_CRAWLER_DNS_ISSUE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/positive_geo_target_type.py b/google/ads/googleads/v15/enums/types/positive_geo_target_type.py new file mode 100644 index 000000000..70ffa8a0a --- /dev/null +++ b/google/ads/googleads/v15/enums/types/positive_geo_target_type.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PRESENCE_OR_INTEREST = 5 + SEARCH_INTEREST = 6 + PRESENCE = 7 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/price_extension_price_qualifier.py b/google/ads/googleads/v15/enums/types/price_extension_price_qualifier.py new file mode 100644 index 000000000..9a833654c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/price_extension_price_qualifier.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + FROM = 2 + UP_TO = 3 + AVERAGE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/price_extension_price_unit.py b/google/ads/googleads/v15/enums/types/price_extension_price_unit.py new file mode 100644 index 000000000..10493a7ae --- /dev/null +++ b/google/ads/googleads/v15/enums/types/price_extension_price_unit.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "PriceExtensionPriceUnitEnum", + }, +) + + +class PriceExtensionPriceUnitEnum(proto.Message): + r"""Container for enum describing price extension price unit.""" + + class PriceExtensionPriceUnit(proto.Enum): + r"""Price extension price unit.""" + 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/v15/enums/types/price_extension_type.py b/google/ads/googleads/v15/enums/types/price_extension_type.py new file mode 100644 index 000000000..4cbac976e --- /dev/null +++ b/google/ads/googleads/v15/enums/types/price_extension_type.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "PriceExtensionTypeEnum", + }, +) + + +class PriceExtensionTypeEnum(proto.Message): + r"""Container for enum describing types for a price extension.""" + + class PriceExtensionType(proto.Enum): + r"""Price extension type.""" + 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/v15/enums/types/price_placeholder_field.py b/google/ads/googleads/v15/enums/types/price_placeholder_field.py new file mode 100644 index 000000000..a3d083712 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/price_placeholder_field.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "PricePlaceholderFieldEnum", + }, +) + + +class PricePlaceholderFieldEnum(proto.Message): + r"""Values for Price placeholder fields.""" + + class PricePlaceholderField(proto.Enum): + r"""Possible values for Price placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + TYPE = 2 + PRICE_QUALIFIER = 3 + TRACKING_TEMPLATE = 4 + LANGUAGE = 5 + FINAL_URL_SUFFIX = 6 + ITEM_1_HEADER = 100 + ITEM_1_DESCRIPTION = 101 + ITEM_1_PRICE = 102 + ITEM_1_UNIT = 103 + ITEM_1_FINAL_URLS = 104 + ITEM_1_FINAL_MOBILE_URLS = 105 + ITEM_2_HEADER = 200 + ITEM_2_DESCRIPTION = 201 + ITEM_2_PRICE = 202 + ITEM_2_UNIT = 203 + ITEM_2_FINAL_URLS = 204 + ITEM_2_FINAL_MOBILE_URLS = 205 + ITEM_3_HEADER = 300 + ITEM_3_DESCRIPTION = 301 + ITEM_3_PRICE = 302 + ITEM_3_UNIT = 303 + ITEM_3_FINAL_URLS = 304 + ITEM_3_FINAL_MOBILE_URLS = 305 + ITEM_4_HEADER = 400 + ITEM_4_DESCRIPTION = 401 + ITEM_4_PRICE = 402 + ITEM_4_UNIT = 403 + ITEM_4_FINAL_URLS = 404 + ITEM_4_FINAL_MOBILE_URLS = 405 + ITEM_5_HEADER = 500 + ITEM_5_DESCRIPTION = 501 + ITEM_5_PRICE = 502 + ITEM_5_UNIT = 503 + ITEM_5_FINAL_URLS = 504 + ITEM_5_FINAL_MOBILE_URLS = 505 + ITEM_6_HEADER = 600 + ITEM_6_DESCRIPTION = 601 + ITEM_6_PRICE = 602 + ITEM_6_UNIT = 603 + ITEM_6_FINAL_URLS = 604 + ITEM_6_FINAL_MOBILE_URLS = 605 + ITEM_7_HEADER = 700 + ITEM_7_DESCRIPTION = 701 + ITEM_7_PRICE = 702 + ITEM_7_UNIT = 703 + ITEM_7_FINAL_URLS = 704 + ITEM_7_FINAL_MOBILE_URLS = 705 + ITEM_8_HEADER = 800 + ITEM_8_DESCRIPTION = 801 + ITEM_8_PRICE = 802 + ITEM_8_UNIT = 803 + ITEM_8_FINAL_URLS = 804 + ITEM_8_FINAL_MOBILE_URLS = 805 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/product_category_level.py b/google/ads/googleads/v15/enums/types/product_category_level.py new file mode 100644 index 000000000..0837b4881 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/product_category_level.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/product_category_state.py b/google/ads/googleads/v15/enums/types/product_category_state.py new file mode 100644 index 000000000..bcbad831b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/product_category_state.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + OBSOLETE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/product_channel.py b/google/ads/googleads/v15/enums/types/product_channel.py new file mode 100644 index 000000000..09f1843b5 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/product_channel.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ONLINE = 2 + LOCAL = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/product_channel_exclusivity.py b/google/ads/googleads/v15/enums/types/product_channel_exclusivity.py new file mode 100644 index 000000000..e93141753 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/product_channel_exclusivity.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + SINGLE_CHANNEL = 2 + MULTI_CHANNEL = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/product_condition.py b/google/ads/googleads/v15/enums/types/product_condition.py new file mode 100644 index 000000000..2538315e9 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/product_condition.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + NEW = 3 + REFURBISHED = 4 + USED = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/product_custom_attribute_index.py b/google/ads/googleads/v15/enums/types/product_custom_attribute_index.py new file mode 100644 index 000000000..6c85f8779 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/product_custom_attribute_index.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/product_link_invitation_status.py b/google/ads/googleads/v15/enums/types/product_link_invitation_status.py new file mode 100644 index 000000000..46ddda465 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/product_link_invitation_status.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/product_type_level.py b/google/ads/googleads/v15/enums/types/product_type_level.py new file mode 100644 index 000000000..7b5973c1d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/product_type_level.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/promotion_extension_discount_modifier.py b/google/ads/googleads/v15/enums/types/promotion_extension_discount_modifier.py new file mode 100644 index 000000000..2c75a1d03 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/promotion_extension_discount_modifier.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + UP_TO = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/promotion_extension_occasion.py b/google/ads/googleads/v15/enums/types/promotion_extension_occasion.py new file mode 100644 index 000000000..245fb55fd --- /dev/null +++ b/google/ads/googleads/v15/enums/types/promotion_extension_occasion.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/promotion_placeholder_field.py b/google/ads/googleads/v15/enums/types/promotion_placeholder_field.py new file mode 100644 index 000000000..b52375f48 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/promotion_placeholder_field.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "PromotionPlaceholderFieldEnum", + }, +) + + +class PromotionPlaceholderFieldEnum(proto.Message): + r"""Values for Promotion placeholder fields.""" + + class PromotionPlaceholderField(proto.Enum): + r"""Possible values for Promotion placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PROMOTION_TARGET = 2 + DISCOUNT_MODIFIER = 3 + PERCENT_OFF = 4 + MONEY_AMOUNT_OFF = 5 + PROMOTION_CODE = 6 + ORDERS_OVER_AMOUNT = 7 + PROMOTION_START = 8 + PROMOTION_END = 9 + OCCASION = 10 + FINAL_URLS = 11 + FINAL_MOBILE_URLS = 12 + TRACKING_URL = 13 + LANGUAGE = 14 + FINAL_URL_SUFFIX = 15 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/proximity_radius_units.py b/google/ads/googleads/v15/enums/types/proximity_radius_units.py new file mode 100644 index 000000000..92f5d018f --- /dev/null +++ b/google/ads/googleads/v15/enums/types/proximity_radius_units.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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)""" + UNSPECIFIED = 0 + UNKNOWN = 1 + MILES = 2 + KILOMETERS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/quality_score_bucket.py b/google/ads/googleads/v15/enums/types/quality_score_bucket.py new file mode 100644 index 000000000..dc4d68bbc --- /dev/null +++ b/google/ads/googleads/v15/enums/types/quality_score_bucket.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + BELOW_AVERAGE = 2 + AVERAGE = 3 + ABOVE_AVERAGE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/reach_plan_age_range.py b/google/ads/googleads/v15/enums/types/reach_plan_age_range.py new file mode 100644 index 000000000..3e562dfbf --- /dev/null +++ b/google/ads/googleads/v15/enums/types/reach_plan_age_range.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "ReachPlanAgeRangeEnum", + }, +) + + +class ReachPlanAgeRangeEnum(proto.Message): + r"""Message describing plannable age ranges.""" + + class ReachPlanAgeRange(proto.Enum): + r"""Possible plannable age range values.""" + 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_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/v15/enums/types/reach_plan_network.py b/google/ads/googleads/v15/enums/types/reach_plan_network.py new file mode 100644 index 000000000..2faeea582 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/reach_plan_network.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "ReachPlanNetworkEnum", + }, +) + + +class ReachPlanNetworkEnum(proto.Message): + r"""Container for enum describing plannable networks.""" + + class ReachPlanNetwork(proto.Enum): + r"""Possible plannable network values.""" + 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/v15/enums/types/reach_plan_surface.py b/google/ads/googleads/v15/enums/types/reach_plan_surface.py new file mode 100644 index 000000000..6f67487e4 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/reach_plan_surface.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + IN_FEED = 2 + IN_STREAM_BUMPER = 3 + IN_STREAM_NON_SKIPPABLE = 4 + IN_STREAM_SKIPPABLE = 5 + SHORTS = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/real_estate_placeholder_field.py b/google/ads/googleads/v15/enums/types/real_estate_placeholder_field.py new file mode 100644 index 000000000..4dec329f0 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/real_estate_placeholder_field.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "RealEstatePlaceholderFieldEnum", + }, +) + + +class RealEstatePlaceholderFieldEnum(proto.Message): + r"""Values for Real Estate placeholder fields. + For more information about dynamic remarketing feeds, see + https://support.google.com/google-ads/answer/6053288. + + """ + + class RealEstatePlaceholderField(proto.Enum): + r"""Possible values for Real Estate placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + LISTING_ID = 2 + LISTING_NAME = 3 + CITY_NAME = 4 + DESCRIPTION = 5 + ADDRESS = 6 + PRICE = 7 + FORMATTED_PRICE = 8 + IMAGE_URL = 9 + PROPERTY_TYPE = 10 + LISTING_TYPE = 11 + CONTEXTUAL_KEYWORDS = 12 + FINAL_URLS = 13 + FINAL_MOBILE_URLS = 14 + TRACKING_URL = 15 + ANDROID_APP_LINK = 16 + SIMILAR_LISTING_IDS = 17 + IOS_APP_LINK = 18 + IOS_APP_STORE_ID = 19 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/recommendation_subscription_status.py b/google/ads/googleads/v15/enums/types/recommendation_subscription_status.py new file mode 100644 index 000000000..dca925328 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/recommendation_subscription_status.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "RecommendationSubscriptionStatusEnum", + }, +) + + +class RecommendationSubscriptionStatusEnum(proto.Message): + r"""Container for enum describing recommendation subscription + statuses. + + """ + + class RecommendationSubscriptionStatus(proto.Enum): + r"""Enum describing recommendation subscription statuses.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + PAUSED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/recommendation_type.py b/google/ads/googleads/v15/enums/types/recommendation_type.py new file mode 100644 index 000000000..da80bfeda --- /dev/null +++ b/google/ads/googleads/v15/enums/types/recommendation_type.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "RecommendationTypeEnum", + }, +) + + +class RecommendationTypeEnum(proto.Message): + r"""Container for enum describing types of recommendations.""" + + class RecommendationType(proto.Enum): + r"""Types of recommendations.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/resource_change_operation.py b/google/ads/googleads/v15/enums/types/resource_change_operation.py new file mode 100644 index 000000000..b228bb0ff --- /dev/null +++ b/google/ads/googleads/v15/enums/types/resource_change_operation.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CREATE = 2 + UPDATE = 3 + REMOVE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/resource_limit_type.py b/google/ads/googleads/v15/enums/types/resource_limit_type.py new file mode 100644 index 000000000..ee248d9a9 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/resource_limit_type.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "ResourceLimitTypeEnum", + }, +) + + +class ResourceLimitTypeEnum(proto.Message): + r"""Container for enum describing possible resource limit types.""" + + class ResourceLimitType(proto.Enum): + r"""Resource limit type.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/response_content_type.py b/google/ads/googleads/v15/enums/types/response_content_type.py new file mode 100644 index 000000000..12b409ccc --- /dev/null +++ b/google/ads/googleads/v15/enums/types/response_content_type.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "ResponseContentTypeEnum", + }, +) + + +class ResponseContentTypeEnum(proto.Message): + r"""Container for possible response content types.""" + + class ResponseContentType(proto.Enum): + r"""Possible response content types.""" + UNSPECIFIED = 0 + RESOURCE_NAME_ONLY = 1 + MUTABLE_RESOURCE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/search_engine_results_page_type.py b/google/ads/googleads/v15/enums/types/search_engine_results_page_type.py new file mode 100644 index 000000000..50242bbb5 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/search_engine_results_page_type.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/search_term_match_type.py b/google/ads/googleads/v15/enums/types/search_term_match_type.py new file mode 100644 index 000000000..092628c07 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/search_term_match_type.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + BROAD = 2 + EXACT = 3 + PHRASE = 4 + NEAR_EXACT = 5 + NEAR_PHRASE = 6 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/search_term_targeting_status.py b/google/ads/googleads/v15/enums/types/search_term_targeting_status.py new file mode 100644 index 000000000..ef147763b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/search_term_targeting_status.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + ADDED = 2 + EXCLUDED = 3 + ADDED_EXCLUDED = 4 + NONE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/seasonality_event_scope.py b/google/ads/googleads/v15/enums/types/seasonality_event_scope.py new file mode 100644 index 000000000..95fe5534c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/seasonality_event_scope.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER = 2 + CAMPAIGN = 4 + CHANNEL = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/seasonality_event_status.py b/google/ads/googleads/v15/enums/types/seasonality_event_status.py new file mode 100644 index 000000000..de27eac83 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/seasonality_event_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/served_asset_field_type.py b/google/ads/googleads/v15/enums/types/served_asset_field_type.py new file mode 100644 index 000000000..ff2c10572 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/served_asset_field_type.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/shared_set_status.py b/google/ads/googleads/v15/enums/types/shared_set_status.py new file mode 100644 index 000000000..a7c134bdc --- /dev/null +++ b/google/ads/googleads/v15/enums/types/shared_set_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + REMOVED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/shared_set_type.py b/google/ads/googleads/v15/enums/types/shared_set_type.py new file mode 100644 index 000000000..da20dd31a --- /dev/null +++ b/google/ads/googleads/v15/enums/types/shared_set_type.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + NEGATIVE_KEYWORDS = 2 + NEGATIVE_PLACEMENTS = 3 + ACCOUNT_LEVEL_NEGATIVE_KEYWORDS = 4 + BRANDS = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/shopping_add_products_to_campaign_recommendation_enum.py b/google/ads/googleads/v15/enums/types/shopping_add_products_to_campaign_recommendation_enum.py new file mode 100644 index 000000000..2dae2665f --- /dev/null +++ b/google/ads/googleads/v15/enums/types/shopping_add_products_to_campaign_recommendation_enum.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/simulation_modification_method.py b/google/ads/googleads/v15/enums/types/simulation_modification_method.py new file mode 100644 index 000000000..c9e97c6fc --- /dev/null +++ b/google/ads/googleads/v15/enums/types/simulation_modification_method.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + UNIFORM = 2 + DEFAULT = 3 + SCALING = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/simulation_type.py b/google/ads/googleads/v15/enums/types/simulation_type.py new file mode 100644 index 000000000..a4025aa8b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/simulation_type.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/sitelink_placeholder_field.py b/google/ads/googleads/v15/enums/types/sitelink_placeholder_field.py new file mode 100644 index 000000000..688e3a7da --- /dev/null +++ b/google/ads/googleads/v15/enums/types/sitelink_placeholder_field.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "SitelinkPlaceholderFieldEnum", + }, +) + + +class SitelinkPlaceholderFieldEnum(proto.Message): + r"""Values for Sitelink placeholder fields.""" + + class SitelinkPlaceholderField(proto.Enum): + r"""Possible values for Sitelink placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + TEXT = 2 + LINE_1 = 3 + LINE_2 = 4 + FINAL_URLS = 5 + FINAL_MOBILE_URLS = 6 + TRACKING_URL = 7 + FINAL_URL_SUFFIX = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/sk_ad_network_ad_event_type.py b/google/ads/googleads/v15/enums/types/sk_ad_network_ad_event_type.py new file mode 100644 index 000000000..a1a705674 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/sk_ad_network_ad_event_type.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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""" + UNSPECIFIED = 0 + UNKNOWN = 1 + UNAVAILABLE = 2 + INTERACTION = 3 + VIEW = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/sk_ad_network_attribution_credit.py b/google/ads/googleads/v15/enums/types/sk_ad_network_attribution_credit.py new file mode 100644 index 000000000..69ac099ad --- /dev/null +++ b/google/ads/googleads/v15/enums/types/sk_ad_network_attribution_credit.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "SkAdNetworkAttributionCreditEnum", + }, +) + + +class SkAdNetworkAttributionCreditEnum(proto.Message): + r"""Container for enumeration of SkAdNetwork attribution credits.""" + + class SkAdNetworkAttributionCredit(proto.Enum): + r"""Enumerates SkAdNetwork attribution credits.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + UNAVAILABLE = 2 + WON = 3 + CONTRIBUTED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/sk_ad_network_coarse_conversion_value.py b/google/ads/googleads/v15/enums/types/sk_ad_network_coarse_conversion_value.py new file mode 100644 index 000000000..d4ac99625 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/sk_ad_network_coarse_conversion_value.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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""" + 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/v15/enums/types/sk_ad_network_source_type.py b/google/ads/googleads/v15/enums/types/sk_ad_network_source_type.py new file mode 100644 index 000000000..8b140d845 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/sk_ad_network_source_type.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "SkAdNetworkSourceTypeEnum", + }, +) + + +class SkAdNetworkSourceTypeEnum(proto.Message): + r"""Container for enumeration of SkAdNetwork source types.""" + + class SkAdNetworkSourceType(proto.Enum): + r"""Enumerates SkAdNetwork source types""" + UNSPECIFIED = 0 + UNKNOWN = 1 + UNAVAILABLE = 2 + WEBSITE = 3 + MOBILE_APPLICATION = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/sk_ad_network_user_type.py b/google/ads/googleads/v15/enums/types/sk_ad_network_user_type.py new file mode 100644 index 000000000..6d9efe275 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/sk_ad_network_user_type.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "SkAdNetworkUserTypeEnum", + }, +) + + +class SkAdNetworkUserTypeEnum(proto.Message): + r"""Container for enumeration of SkAdNetwork user types.""" + + class SkAdNetworkUserType(proto.Enum): + r"""Enumerates SkAdNetwork user types""" + UNSPECIFIED = 0 + UNKNOWN = 1 + UNAVAILABLE = 2 + NEW_INSTALLER = 3 + REINSTALLER = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/slot.py b/google/ads/googleads/v15/enums/types/slot.py new file mode 100644 index 000000000..af92a46bb --- /dev/null +++ b/google/ads/googleads/v15/enums/types/slot.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/smart_campaign_not_eligible_reason.py b/google/ads/googleads/v15/enums/types/smart_campaign_not_eligible_reason.py new file mode 100644 index 000000000..665c96999 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/smart_campaign_not_eligible_reason.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/smart_campaign_status.py b/google/ads/googleads/v15/enums/types/smart_campaign_status.py new file mode 100644 index 000000000..2d508e83d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/smart_campaign_status.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/spending_limit_type.py b/google/ads/googleads/v15/enums/types/spending_limit_type.py new file mode 100644 index 000000000..37ce20b0e --- /dev/null +++ b/google/ads/googleads/v15/enums/types/spending_limit_type.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + INFINITE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/structured_snippet_placeholder_field.py b/google/ads/googleads/v15/enums/types/structured_snippet_placeholder_field.py new file mode 100644 index 000000000..79754b6a3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/structured_snippet_placeholder_field.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "StructuredSnippetPlaceholderFieldEnum", + }, +) + + +class StructuredSnippetPlaceholderFieldEnum(proto.Message): + r"""Values for Structured Snippet placeholder fields.""" + + class StructuredSnippetPlaceholderField(proto.Enum): + r"""Possible values for Structured Snippet placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + HEADER = 2 + SNIPPETS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/summary_row_setting.py b/google/ads/googleads/v15/enums/types/summary_row_setting.py new file mode 100644 index 000000000..08eed6c4c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/summary_row_setting.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/system_managed_entity_source.py b/google/ads/googleads/v15/enums/types/system_managed_entity_source.py new file mode 100644 index 000000000..40346e41e --- /dev/null +++ b/google/ads/googleads/v15/enums/types/system_managed_entity_source.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + AD_VARIATIONS = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/target_cpa_opt_in_recommendation_goal.py b/google/ads/googleads/v15/enums/types/target_cpa_opt_in_recommendation_goal.py new file mode 100644 index 000000000..32931a718 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/target_cpa_opt_in_recommendation_goal.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "TargetCpaOptInRecommendationGoalEnum", + }, +) + + +class TargetCpaOptInRecommendationGoalEnum(proto.Message): + r"""Container for enum describing goals for TargetCpaOptIn + recommendation. + + """ + + class TargetCpaOptInRecommendationGoal(proto.Enum): + r"""Goal of TargetCpaOptIn recommendation.""" + 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/v15/enums/types/target_frequency_time_unit.py b/google/ads/googleads/v15/enums/types/target_frequency_time_unit.py new file mode 100644 index 000000000..9df3e54b3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/target_frequency_time_unit.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + WEEKLY = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/target_impression_share_location.py b/google/ads/googleads/v15/enums/types/target_impression_share_location.py new file mode 100644 index 000000000..926c06f4a --- /dev/null +++ b/google/ads/googleads/v15/enums/types/target_impression_share_location.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/targeting_dimension.py b/google/ads/googleads/v15/enums/types/targeting_dimension.py new file mode 100644 index 000000000..57543dcfc --- /dev/null +++ b/google/ads/googleads/v15/enums/types/targeting_dimension.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "TargetingDimensionEnum", + }, +) + + +class TargetingDimensionEnum(proto.Message): + r"""The dimensions that can be targeted.""" + + class TargetingDimension(proto.Enum): + r"""Enum describing possible targeting dimensions.""" + 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/v15/enums/types/time_type.py b/google/ads/googleads/v15/enums/types/time_type.py new file mode 100644 index 000000000..63f23284c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/time_type.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + NOW = 2 + FOREVER = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/tracking_code_page_format.py b/google/ads/googleads/v15/enums/types/tracking_code_page_format.py new file mode 100644 index 000000000..bdb3995e4 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/tracking_code_page_format.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + HTML = 2 + AMP = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/tracking_code_type.py b/google/ads/googleads/v15/enums/types/tracking_code_type.py new file mode 100644 index 000000000..3c0624b8f --- /dev/null +++ b/google/ads/googleads/v15/enums/types/tracking_code_type.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/travel_placeholder_field.py b/google/ads/googleads/v15/enums/types/travel_placeholder_field.py new file mode 100644 index 000000000..fcb44dad3 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/travel_placeholder_field.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "TravelPlaceholderFieldEnum", + }, +) + + +class TravelPlaceholderFieldEnum(proto.Message): + r"""Values for Travel placeholder fields. + For more information about dynamic remarketing feeds, see + https://support.google.com/google-ads/answer/6053288. + + """ + + class TravelPlaceholderField(proto.Enum): + r"""Possible values for Travel placeholder fields.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + DESTINATION_ID = 2 + ORIGIN_ID = 3 + TITLE = 4 + DESTINATION_NAME = 5 + ORIGIN_NAME = 6 + PRICE = 7 + FORMATTED_PRICE = 8 + SALE_PRICE = 9 + FORMATTED_SALE_PRICE = 10 + IMAGE_URL = 11 + CATEGORY = 12 + CONTEXTUAL_KEYWORDS = 13 + DESTINATION_ADDRESS = 14 + FINAL_URL = 15 + FINAL_MOBILE_URLS = 16 + TRACKING_URL = 17 + ANDROID_APP_LINK = 18 + SIMILAR_DESTINATION_IDS = 19 + IOS_APP_LINK = 20 + IOS_APP_STORE_ID = 21 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/user_identifier_source.py b/google/ads/googleads/v15/enums/types/user_identifier_source.py new file mode 100644 index 000000000..a0de27ede --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_identifier_source.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + FIRST_PARTY = 2 + THIRD_PARTY = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/user_interest_taxonomy_type.py b/google/ads/googleads/v15/enums/types/user_interest_taxonomy_type.py new file mode 100644 index 000000000..946029d44 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_interest_taxonomy_type.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "UserInterestTaxonomyTypeEnum", + }, +) + + +class UserInterestTaxonomyTypeEnum(proto.Message): + r"""Message describing a UserInterestTaxonomyType.""" + + class UserInterestTaxonomyType(proto.Enum): + r"""Enum containing the possible UserInterestTaxonomyTypes.""" + 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/v15/enums/types/user_list_access_status.py b/google/ads/googleads/v15/enums/types/user_list_access_status.py new file mode 100644 index 000000000..2d1a0d350 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_list_access_status.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENABLED = 2 + DISABLED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/user_list_closing_reason.py b/google/ads/googleads/v15/enums/types/user_list_closing_reason.py new file mode 100644 index 000000000..d20dc120c --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_list_closing_reason.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + UNUSED = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/user_list_crm_data_source_type.py b/google/ads/googleads/v15/enums/types/user_list_crm_data_source_type.py new file mode 100644 index 000000000..372220e12 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_list_crm_data_source_type.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + FIRST_PARTY = 2 + THIRD_PARTY_CREDIT_BUREAU = 3 + THIRD_PARTY_VOTER_FILE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/user_list_date_rule_item_operator.py b/google/ads/googleads/v15/enums/types/user_list_date_rule_item_operator.py new file mode 100644 index 000000000..795187e4b --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_list_date_rule_item_operator.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + EQUALS = 2 + NOT_EQUALS = 3 + BEFORE = 4 + AFTER = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/user_list_flexible_rule_operator.py b/google/ads/googleads/v15/enums/types/user_list_flexible_rule_operator.py new file mode 100644 index 000000000..59c67fd1d --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_list_flexible_rule_operator.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + AND = 2 + OR = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/user_list_logical_rule_operator.py b/google/ads/googleads/v15/enums/types/user_list_logical_rule_operator.py new file mode 100644 index 000000000..9a8898d82 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_list_logical_rule_operator.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ALL = 2 + ANY = 3 + NONE = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/user_list_membership_status.py b/google/ads/googleads/v15/enums/types/user_list_membership_status.py new file mode 100644 index 000000000..b6e871231 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_list_membership_status.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + OPEN = 2 + CLOSED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/user_list_number_rule_item_operator.py b/google/ads/googleads/v15/enums/types/user_list_number_rule_item_operator.py new file mode 100644 index 000000000..a350c6ec4 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_list_number_rule_item_operator.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/user_list_prepopulation_status.py b/google/ads/googleads/v15/enums/types/user_list_prepopulation_status.py new file mode 100644 index 000000000..098e49dfb --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_list_prepopulation_status.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + REQUESTED = 2 + FINISHED = 3 + FAILED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/user_list_rule_type.py b/google/ads/googleads/v15/enums/types/user_list_rule_type.py new file mode 100644 index 000000000..ca7913bc1 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_list_rule_type.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + AND_OF_ORS = 2 + OR_OF_ANDS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/user_list_size_range.py b/google/ads/googleads/v15/enums/types/user_list_size_range.py new file mode 100644 index 000000000..7cb78b334 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_list_size_range.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/user_list_string_rule_item_operator.py b/google/ads/googleads/v15/enums/types/user_list_string_rule_item_operator.py new file mode 100644 index 000000000..2bda4befb --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_list_string_rule_item_operator.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/enums/types/user_list_type.py b/google/ads/googleads/v15/enums/types/user_list_type.py new file mode 100644 index 000000000..52eeaf261 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/user_list_type.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + manifest={ + "UserListTypeEnum", + }, +) + + +class UserListTypeEnum(proto.Message): + r"""The user list types.""" + + class UserListType(proto.Enum): + r"""Enum containing possible user list types.""" + 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/v15/enums/types/value_rule_device_type.py b/google/ads/googleads/v15/enums/types/value_rule_device_type.py new file mode 100644 index 000000000..f57f9eee4 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/value_rule_device_type.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + MOBILE = 2 + DESKTOP = 3 + TABLET = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/value_rule_geo_location_match_type.py b/google/ads/googleads/v15/enums/types/value_rule_geo_location_match_type.py new file mode 100644 index 000000000..784a2ba56 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/value_rule_geo_location_match_type.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ANY = 2 + LOCATION_OF_PRESENCE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/value_rule_operation.py b/google/ads/googleads/v15/enums/types/value_rule_operation.py new file mode 100644 index 000000000..bafb7adf6 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/value_rule_operation.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ADD = 2 + MULTIPLY = 3 + SET = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/value_rule_set_attachment_type.py b/google/ads/googleads/v15/enums/types/value_rule_set_attachment_type.py new file mode 100644 index 000000000..21ba5261f --- /dev/null +++ b/google/ads/googleads/v15/enums/types/value_rule_set_attachment_type.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER = 2 + CAMPAIGN = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/value_rule_set_dimension.py b/google/ads/googleads/v15/enums/types/value_rule_set_dimension.py new file mode 100644 index 000000000..f2c169424 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/value_rule_set_dimension.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + GEO_LOCATION = 2 + DEVICE = 3 + AUDIENCE = 4 + NO_CONDITION = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/vanity_pharma_display_url_mode.py b/google/ads/googleads/v15/enums/types/vanity_pharma_display_url_mode.py new file mode 100644 index 000000000..5390da347 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/vanity_pharma_display_url_mode.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + MANUFACTURER_WEBSITE_URL = 2 + WEBSITE_DESCRIPTION = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/enums/types/vanity_pharma_text.py b/google/ads/googleads/v15/enums/types/vanity_pharma_text.py new file mode 100644 index 000000000..e0562d40a --- /dev/null +++ b/google/ads/googleads/v15/enums/types/vanity_pharma_text.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/video_thumbnail.py b/google/ads/googleads/v15/enums/types/video_thumbnail.py new file mode 100644 index 000000000..ab8f0c027 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/video_thumbnail.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/webpage_condition_operand.py b/google/ads/googleads/v15/enums/types/webpage_condition_operand.py new file mode 100644 index 000000000..87ec83a32 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/webpage_condition_operand.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/enums/types/webpage_condition_operator.py b/google/ads/googleads/v15/enums/types/webpage_condition_operator.py new file mode 100644 index 000000000..cdd2e6291 --- /dev/null +++ b/google/ads/googleads/v15/enums/types/webpage_condition_operator.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.enums", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + EQUALS = 2 + CONTAINS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/__init__.py b/google/ads/googleads/v15/errors/__init__.py new file mode 100644 index 000000000..e162e0df4 --- /dev/null +++ b/google/ads/googleads/v15/errors/__init__.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +__all__ = ( + "AccessInvitationErrorEnum", + "AccountBudgetProposalErrorEnum", + "AccountLinkErrorEnum", + "AdCustomizerErrorEnum", + "AdErrorEnum", + "AdGroupAdErrorEnum", + "AdGroupBidModifierErrorEnum", + "AdGroupCriterionCustomizerErrorEnum", + "AdGroupCriterionErrorEnum", + "AdGroupCustomizerErrorEnum", + "AdGroupErrorEnum", + "AdGroupFeedErrorEnum", + "AdParameterErrorEnum", + "AdSharingErrorEnum", + "AdxErrorEnum", + "AssetErrorEnum", + "AssetGroupAssetErrorEnum", + "AssetGroupErrorEnum", + "AssetGroupListingGroupFilterErrorEnum", + "AssetGroupSignalErrorEnum", + "AssetLinkErrorEnum", + "AssetSetAssetErrorEnum", + "AssetSetErrorEnum", + "AssetSetLinkErrorEnum", + "AudienceErrorEnum", + "AudienceInsightsErrorEnum", + "AuthenticationErrorEnum", + "AuthorizationErrorEnum", + "BatchJobErrorEnum", + "BiddingErrorEnum", + "BiddingStrategyErrorEnum", + "BillingSetupErrorEnum", + "CampaignBudgetErrorEnum", + "CampaignConversionGoalErrorEnum", + "CampaignCriterionErrorEnum", + "CampaignCustomizerErrorEnum", + "CampaignDraftErrorEnum", + "CampaignErrorEnum", + "CampaignExperimentErrorEnum", + "CampaignFeedErrorEnum", + "CampaignLifecycleGoalErrorEnum", + "CampaignSharedSetErrorEnum", + "ChangeEventErrorEnum", + "ChangeStatusErrorEnum", + "CollectionSizeErrorEnum", + "ContextErrorEnum", + "ConversionActionErrorEnum", + "ConversionAdjustmentUploadErrorEnum", + "ConversionCustomVariableErrorEnum", + "ConversionGoalCampaignConfigErrorEnum", + "ConversionUploadErrorEnum", + "ConversionValueRuleErrorEnum", + "ConversionValueRuleSetErrorEnum", + "CountryCodeErrorEnum", + "CriterionErrorEnum", + "CurrencyCodeErrorEnum", + "CurrencyErrorEnum", + "CustomAudienceErrorEnum", + "CustomConversionGoalErrorEnum", + "CustomInterestErrorEnum", + "CustomerClientLinkErrorEnum", + "CustomerCustomizerErrorEnum", + "CustomerErrorEnum", + "CustomerFeedErrorEnum", + "CustomerLifecycleGoalErrorEnum", + "CustomerManagerLinkErrorEnum", + "CustomerSkAdNetworkConversionValueSchemaErrorEnum", + "CustomerUserAccessErrorEnum", + "CustomizerAttributeErrorEnum", + "DatabaseErrorEnum", + "DateErrorEnum", + "DateRangeErrorEnum", + "DistinctErrorEnum", + "EnumErrorEnum", + "ErrorCode", + "ErrorDetails", + "ErrorLocation", + "ExperimentArmErrorEnum", + "ExperimentErrorEnum", + "ExtensionFeedItemErrorEnum", + "ExtensionSettingErrorEnum", + "FeedAttributeReferenceErrorEnum", + "FeedErrorEnum", + "FeedItemErrorEnum", + "FeedItemSetErrorEnum", + "FeedItemSetLinkErrorEnum", + "FeedItemTargetErrorEnum", + "FeedItemValidationErrorEnum", + "FeedMappingErrorEnum", + "FieldErrorEnum", + "FieldMaskErrorEnum", + "FunctionErrorEnum", + "FunctionParsingErrorEnum", + "GeoTargetConstantSuggestionErrorEnum", + "GoogleAdsError", + "GoogleAdsFailure", + "HeaderErrorEnum", + "IdErrorEnum", + "ImageErrorEnum", + "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", + "ResourceAccessDeniedErrorEnum", + "ResourceCountDetails", + "ResourceCountLimitExceededErrorEnum", + "SearchTermInsightErrorEnum", + "SettingErrorEnum", + "SharedCriterionErrorEnum", + "SharedSetErrorEnum", + "SizeLimitErrorEnum", + "SmartCampaignErrorEnum", + "StringFormatErrorEnum", + "StringLengthErrorEnum", + "ThirdPartyAppAnalyticsLinkErrorEnum", + "TimeZoneErrorEnum", + "UrlFieldErrorEnum", + "UserDataErrorEnum", + "UserListErrorEnum", + "YoutubeVideoRegistrationErrorEnum", +) diff --git a/google/ads/googleads/v15/errors/services/__init__.py b/google/ads/googleads/v15/errors/services/__init__.py new file mode 100644 index 000000000..89a37dc92 --- /dev/null +++ b/google/ads/googleads/v15/errors/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/v15/errors/types/__init__.py b/google/ads/googleads/v15/errors/types/__init__.py new file mode 100644 index 000000000..89a37dc92 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/v15/errors/types/access_invitation_error.py b/google/ads/googleads/v15/errors/types/access_invitation_error.py new file mode 100644 index 000000000..216d58ccb --- /dev/null +++ b/google/ads/googleads/v15/errors/types/access_invitation_error.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "AccessInvitationErrorEnum", + }, +) + + +class AccessInvitationErrorEnum(proto.Message): + r"""Container for enum describing possible AccessInvitation + errors. + + """ + + class AccessInvitationError(proto.Enum): + r"""Enum describing possible AccessInvitation errors.""" + 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/v15/errors/types/account_budget_proposal_error.py b/google/ads/googleads/v15/errors/types/account_budget_proposal_error.py new file mode 100644 index 000000000..8a243188d --- /dev/null +++ b/google/ads/googleads/v15/errors/types/account_budget_proposal_error.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/account_link_error.py b/google/ads/googleads/v15/errors/types/account_link_error.py new file mode 100644 index 000000000..fceffe40b --- /dev/null +++ b/google/ads/googleads/v15/errors/types/account_link_error.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_STATUS = 2 + PERMISSION_DENIED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/ad_customizer_error.py b/google/ads/googleads/v15/errors/types/ad_customizer_error.py new file mode 100644 index 000000000..146763111 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/ad_customizer_error.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/ad_error.py b/google/ads/googleads/v15/errors/types/ad_error.py new file mode 100644 index 000000000..37aae2adb --- /dev/null +++ b/google/ads/googleads/v15/errors/types/ad_error.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "AdErrorEnum", + }, +) + + +class AdErrorEnum(proto.Message): + r"""Container for enum describing possible ad errors.""" + + class AdError(proto.Enum): + r"""Enum describing possible ad errors.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/ad_group_ad_error.py b/google/ads/googleads/v15/errors/types/ad_group_ad_error.py new file mode 100644 index 000000000..c677064b2 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/ad_group_ad_error.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/ad_group_bid_modifier_error.py b/google/ads/googleads/v15/errors/types/ad_group_bid_modifier_error.py new file mode 100644 index 000000000..e3d7f3e5b --- /dev/null +++ b/google/ads/googleads/v15/errors/types/ad_group_bid_modifier_error.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/ad_group_criterion_customizer_error.py b/google/ads/googleads/v15/errors/types/ad_group_criterion_customizer_error.py new file mode 100644 index 000000000..d427341ce --- /dev/null +++ b/google/ads/googleads/v15/errors/types/ad_group_criterion_customizer_error.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + CRITERION_IS_NOT_KEYWORD = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/ad_group_criterion_error.py b/google/ads/googleads/v15/errors/types/ad_group_criterion_error.py new file mode 100644 index 000000000..e1549b4fb --- /dev/null +++ b/google/ads/googleads/v15/errors/types/ad_group_criterion_error.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/ad_group_customizer_error.py b/google/ads/googleads/v15/errors/types/ad_group_customizer_error.py new file mode 100644 index 000000000..372233b84 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/ad_group_customizer_error.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/ad_group_error.py b/google/ads/googleads/v15/errors/types/ad_group_error.py new file mode 100644 index 000000000..35aee5353 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/ad_group_error.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/ad_group_feed_error.py b/google/ads/googleads/v15/errors/types/ad_group_feed_error.py new file mode 100644 index 000000000..1fae833cf --- /dev/null +++ b/google/ads/googleads/v15/errors/types/ad_group_feed_error.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/ad_parameter_error.py b/google/ads/googleads/v15/errors/types/ad_parameter_error.py new file mode 100644 index 000000000..0f4607512 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/ad_parameter_error.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/ad_sharing_error.py b/google/ads/googleads/v15/errors/types/ad_sharing_error.py new file mode 100644 index 000000000..91a3bf839 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/ad_sharing_error.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/adx_error.py b/google/ads/googleads/v15/errors/types/adx_error.py new file mode 100644 index 000000000..dd01e79e6 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/adx_error.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "AdxErrorEnum", + }, +) + + +class AdxErrorEnum(proto.Message): + r"""Container for enum describing possible adx errors.""" + + class AdxError(proto.Enum): + r"""Enum describing possible adx errors.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + UNSUPPORTED_FEATURE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/asset_error.py b/google/ads/googleads/v15/errors/types/asset_error.py new file mode 100644 index 000000000..17b1f929f --- /dev/null +++ b/google/ads/googleads/v15/errors/types/asset_error.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "AssetErrorEnum", + }, +) + + +class AssetErrorEnum(proto.Message): + r"""Container for enum describing possible asset errors.""" + + class AssetError(proto.Enum): + r"""Enum describing possible asset errors.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/asset_group_asset_error.py b/google/ads/googleads/v15/errors/types/asset_group_asset_error.py new file mode 100644 index 000000000..ecef688c3 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/asset_group_asset_error.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/asset_group_error.py b/google/ads/googleads/v15/errors/types/asset_group_error.py new file mode 100644 index 000000000..0e84201f3 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/asset_group_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/asset_group_listing_group_filter_error.py b/google/ads/googleads/v15/errors/types/asset_group_listing_group_filter_error.py new file mode 100644 index 000000000..5854369a4 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/asset_group_listing_group_filter_error.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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. + """ + 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 + MULTIPLE_OPERATIONS_ON_ONE_NODE = 23 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/asset_group_signal_error.py b/google/ads/googleads/v15/errors/types/asset_group_signal_error.py new file mode 100644 index 000000000..c4dfbcc5f --- /dev/null +++ b/google/ads/googleads/v15/errors/types/asset_group_signal_error.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/asset_link_error.py b/google/ads/googleads/v15/errors/types/asset_link_error.py new file mode 100644 index 000000000..222d4fdac --- /dev/null +++ b/google/ads/googleads/v15/errors/types/asset_link_error.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/asset_set_asset_error.py b/google/ads/googleads/v15/errors/types/asset_set_asset_error.py new file mode 100644 index 000000000..f7d0d0601 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/asset_set_asset_error.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/asset_set_error.py b/google/ads/googleads/v15/errors/types/asset_set_error.py new file mode 100644 index 000000000..f90dcc53a --- /dev/null +++ b/google/ads/googleads/v15/errors/types/asset_set_error.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/asset_set_link_error.py b/google/ads/googleads/v15/errors/types/asset_set_link_error.py new file mode 100644 index 000000000..316261c53 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/asset_set_link_error.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/audience_error.py b/google/ads/googleads/v15/errors/types/audience_error.py new file mode 100644 index 000000000..967ddf28a --- /dev/null +++ b/google/ads/googleads/v15/errors/types/audience_error.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "AudienceErrorEnum", + }, +) + + +class AudienceErrorEnum(proto.Message): + r"""Container for enum describing possible audience errors.""" + + class AudienceError(proto.Enum): + r"""Enum describing possible audience errors.""" + 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/v15/errors/types/audience_insights_error.py b/google/ads/googleads/v15/errors/types/audience_insights_error.py new file mode 100644 index 000000000..0ab4486d7 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/audience_insights_error.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + DIMENSION_INCOMPATIBLE_WITH_TOPIC_AUDIENCE_COMBINATIONS = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/authentication_error.py b/google/ads/googleads/v15/errors/types/authentication_error.py new file mode 100644 index 000000000..8dbc98130 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/authentication_error.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "AuthenticationErrorEnum", + }, +) + + +class AuthenticationErrorEnum(proto.Message): + r"""Container for enum describing possible authentication errors.""" + + class AuthenticationError(proto.Enum): + r"""Enum describing possible authentication errors.""" + 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 + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/authorization_error.py b/google/ads/googleads/v15/errors/types/authorization_error.py new file mode 100644 index 000000000..07f4a5d04 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/authorization_error.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "AuthorizationErrorEnum", + }, +) + + +class AuthorizationErrorEnum(proto.Message): + r"""Container for enum describing possible authorization errors.""" + + class AuthorizationError(proto.Enum): + r"""Enum describing possible authorization errors.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/batch_job_error.py b/google/ads/googleads/v15/errors/types/batch_job_error.py new file mode 100644 index 000000000..ec111056a --- /dev/null +++ b/google/ads/googleads/v15/errors/types/batch_job_error.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/bidding_error.py b/google/ads/googleads/v15/errors/types/bidding_error.py new file mode 100644 index 000000000..bb4c0d4b4 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/bidding_error.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "BiddingErrorEnum", + }, +) + + +class BiddingErrorEnum(proto.Message): + r"""Container for enum describing possible bidding errors.""" + + class BiddingError(proto.Enum): + r"""Enum describing possible bidding errors.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/bidding_strategy_error.py b/google/ads/googleads/v15/errors/types/bidding_strategy_error.py new file mode 100644 index 000000000..09597ba49 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/bidding_strategy_error.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/billing_setup_error.py b/google/ads/googleads/v15/errors/types/billing_setup_error.py new file mode 100644 index 000000000..8ae86f873 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/billing_setup_error.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/campaign_budget_error.py b/google/ads/googleads/v15/errors/types/campaign_budget_error.py new file mode 100644 index 000000000..608bb8cdf --- /dev/null +++ b/google/ads/googleads/v15/errors/types/campaign_budget_error.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/campaign_conversion_goal_error.py b/google/ads/googleads/v15/errors/types/campaign_conversion_goal_error.py new file mode 100644 index 000000000..2ef6d15ba --- /dev/null +++ b/google/ads/googleads/v15/errors/types/campaign_conversion_goal_error.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/campaign_criterion_error.py b/google/ads/googleads/v15/errors/types/campaign_criterion_error.py new file mode 100644 index 000000000..925acf4b3 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/campaign_criterion_error.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/campaign_customizer_error.py b/google/ads/googleads/v15/errors/types/campaign_customizer_error.py new file mode 100644 index 000000000..f509b6266 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/campaign_customizer_error.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/campaign_draft_error.py b/google/ads/googleads/v15/errors/types/campaign_draft_error.py new file mode 100644 index 000000000..cfba91b9b --- /dev/null +++ b/google/ads/googleads/v15/errors/types/campaign_draft_error.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/campaign_error.py b/google/ads/googleads/v15/errors/types/campaign_error.py new file mode 100644 index 000000000..9cece3a11 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/campaign_error.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "CampaignErrorEnum", + }, +) + + +class CampaignErrorEnum(proto.Message): + r"""Container for enum describing possible campaign errors.""" + + class CampaignError(proto.Enum): + r"""Enum describing possible campaign errors.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/campaign_experiment_error.py b/google/ads/googleads/v15/errors/types/campaign_experiment_error.py new file mode 100644 index 000000000..307e642f0 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/campaign_experiment_error.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/campaign_feed_error.py b/google/ads/googleads/v15/errors/types/campaign_feed_error.py new file mode 100644 index 000000000..40734ab36 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/campaign_feed_error.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/campaign_lifecycle_goal_error.py b/google/ads/googleads/v15/errors/types/campaign_lifecycle_goal_error.py new file mode 100644 index 000000000..710ee6bdd --- /dev/null +++ b/google/ads/googleads/v15/errors/types/campaign_lifecycle_goal_error.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/campaign_shared_set_error.py b/google/ads/googleads/v15/errors/types/campaign_shared_set_error.py new file mode 100644 index 000000000..858a025c3 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/campaign_shared_set_error.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + SHARED_SET_ACCESS_DENIED = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/change_event_error.py b/google/ads/googleads/v15/errors/types/change_event_error.py new file mode 100644 index 000000000..c8d7db5f9 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/change_event_error.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/change_status_error.py b/google/ads/googleads/v15/errors/types/change_status_error.py new file mode 100644 index 000000000..6172ab2f1 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/change_status_error.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/collection_size_error.py b/google/ads/googleads/v15/errors/types/collection_size_error.py new file mode 100644 index 000000000..f87f40b62 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/collection_size_error.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + TOO_FEW = 2 + TOO_MANY = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/context_error.py b/google/ads/googleads/v15/errors/types/context_error.py new file mode 100644 index 000000000..adcbb2a9c --- /dev/null +++ b/google/ads/googleads/v15/errors/types/context_error.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "ContextErrorEnum", + }, +) + + +class ContextErrorEnum(proto.Message): + r"""Container for enum describing possible context errors.""" + + class ContextError(proto.Enum): + r"""Enum describing possible context errors.""" + 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/v15/errors/types/conversion_action_error.py b/google/ads/googleads/v15/errors/types/conversion_action_error.py new file mode 100644 index 000000000..1e1ab425a --- /dev/null +++ b/google/ads/googleads/v15/errors/types/conversion_action_error.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/conversion_adjustment_upload_error.py b/google/ads/googleads/v15/errors/types/conversion_adjustment_upload_error.py new file mode 100644 index 000000000..2a4e0673a --- /dev/null +++ b/google/ads/googleads/v15/errors/types/conversion_adjustment_upload_error.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/conversion_custom_variable_error.py b/google/ads/googleads/v15/errors/types/conversion_custom_variable_error.py new file mode 100644 index 000000000..0bb02da5d --- /dev/null +++ b/google/ads/googleads/v15/errors/types/conversion_custom_variable_error.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_NAME = 2 + DUPLICATE_TAG = 3 + RESERVED_TAG = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/conversion_goal_campaign_config_error.py b/google/ads/googleads/v15/errors/types/conversion_goal_campaign_config_error.py new file mode 100644 index 000000000..350ccd7ba --- /dev/null +++ b/google/ads/googleads/v15/errors/types/conversion_goal_campaign_config_error.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/errors/types/conversion_upload_error.py b/google/ads/googleads/v15/errors/types/conversion_upload_error.py new file mode 100644 index 000000000..4c9e75eee --- /dev/null +++ b/google/ads/googleads/v15/errors/types/conversion_upload_error.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/conversion_value_rule_error.py b/google/ads/googleads/v15/errors/types/conversion_value_rule_error.py new file mode 100644 index 000000000..7a5baf87e --- /dev/null +++ b/google/ads/googleads/v15/errors/types/conversion_value_rule_error.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/conversion_value_rule_set_error.py b/google/ads/googleads/v15/errors/types/conversion_value_rule_set_error.py new file mode 100644 index 000000000..94a386578 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/conversion_value_rule_set_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/country_code_error.py b/google/ads/googleads/v15/errors/types/country_code_error.py new file mode 100644 index 000000000..0670084f2 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/country_code_error.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "CountryCodeErrorEnum", + }, +) + + +class CountryCodeErrorEnum(proto.Message): + r"""Container for enum describing country code errors.""" + + class CountryCodeError(proto.Enum): + r"""Enum describing country code errors.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_COUNTRY_CODE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/criterion_error.py b/google/ads/googleads/v15/errors/types/criterion_error.py new file mode 100644 index 000000000..637b9ea2f --- /dev/null +++ b/google/ads/googleads/v15/errors/types/criterion_error.py @@ -0,0 +1,188 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "CriterionErrorEnum", + }, +) + + +class CriterionErrorEnum(proto.Message): + r"""Container for enum describing possible criterion errors.""" + + class CriterionError(proto.Enum): + r"""Enum describing possible criterion errors.""" + 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 + INVALID_LISTING_GROUP_HIERARCHY = 106 + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/currency_code_error.py b/google/ads/googleads/v15/errors/types/currency_code_error.py new file mode 100644 index 000000000..c48b50c50 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/currency_code_error.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + UNSUPPORTED = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/currency_error.py b/google/ads/googleads/v15/errors/types/currency_error.py new file mode 100644 index 000000000..fdf951ed5 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/currency_error.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "CurrencyErrorEnum", + }, +) + + +class CurrencyErrorEnum(proto.Message): + r"""Container for enum describing possible currency errors.""" + + class CurrencyError(proto.Enum): + r"""Enum describing possible currency errors.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + VALUE_NOT_MULTIPLE_OF_BILLABLE_UNIT = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/custom_audience_error.py b/google/ads/googleads/v15/errors/types/custom_audience_error.py new file mode 100644 index 000000000..51496df15 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/custom_audience_error.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/custom_conversion_goal_error.py b/google/ads/googleads/v15/errors/types/custom_conversion_goal_error.py new file mode 100644 index 000000000..539705fd4 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/custom_conversion_goal_error.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/custom_interest_error.py b/google/ads/googleads/v15/errors/types/custom_interest_error.py new file mode 100644 index 000000000..79a1a10fe --- /dev/null +++ b/google/ads/googleads/v15/errors/types/custom_interest_error.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/customer_client_link_error.py b/google/ads/googleads/v15/errors/types/customer_client_link_error.py new file mode 100644 index 000000000..3991efba2 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/customer_client_link_error.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "CustomerClientLinkErrorEnum", + }, +) + + +class CustomerClientLinkErrorEnum(proto.Message): + r"""Container for enum describing possible CustomeClientLink + errors. + + """ + + class CustomerClientLinkError(proto.Enum): + r"""Enum describing possible CustomerClientLink errors.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/customer_customizer_error.py b/google/ads/googleads/v15/errors/types/customer_customizer_error.py new file mode 100644 index 000000000..0fcab82d0 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/customer_customizer_error.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/customer_error.py b/google/ads/googleads/v15/errors/types/customer_error.py new file mode 100644 index 000000000..c15cb1092 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/customer_error.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + STATUS_CHANGE_DISALLOWED = 2 + ACCOUNT_NOT_SET_UP = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/customer_feed_error.py b/google/ads/googleads/v15/errors/types/customer_feed_error.py new file mode 100644 index 000000000..faa8e1962 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/customer_feed_error.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/customer_lifecycle_goal_error.py b/google/ads/googleads/v15/errors/types/customer_lifecycle_goal_error.py new file mode 100644 index 000000000..bd89f589e --- /dev/null +++ b/google/ads/googleads/v15/errors/types/customer_lifecycle_goal_error.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/customer_manager_link_error.py b/google/ads/googleads/v15/errors/types/customer_manager_link_error.py new file mode 100644 index 000000000..05042842a --- /dev/null +++ b/google/ads/googleads/v15/errors/types/customer_manager_link_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "CustomerManagerLinkErrorEnum", + }, +) + + +class CustomerManagerLinkErrorEnum(proto.Message): + r"""Container for enum describing possible CustomerManagerLink + errors. + + """ + + class CustomerManagerLinkError(proto.Enum): + r"""Enum describing possible CustomerManagerLink errors.""" + 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/v15/errors/types/customer_sk_ad_network_conversion_value_schema_error.py b/google/ads/googleads/v15/errors/types/customer_sk_ad_network_conversion_value_schema_error.py new file mode 100644 index 000000000..acd37898d --- /dev/null +++ b/google/ads/googleads/v15/errors/types/customer_sk_ad_network_conversion_value_schema_error.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "CustomerSkAdNetworkConversionValueSchemaErrorEnum", + }, +) + + +class CustomerSkAdNetworkConversionValueSchemaErrorEnum(proto.Message): + r"""Container for enum describing possible + CustomerSkAdNetworkConversionValueSchema errors. + + """ + + class CustomerSkAdNetworkConversionValueSchemaError(proto.Enum): + r"""Enum describing possible + CustomerSkAdNetworkConversionValueSchema errors. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_LINK_ID = 2 + INVALID_APP_ID = 3 + INVALID_SCHEMA = 4 + LINK_CODE_NOT_FOUND = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/customer_user_access_error.py b/google/ads/googleads/v15/errors/types/customer_user_access_error.py new file mode 100644 index 000000000..bba73e471 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/customer_user_access_error.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/customizer_attribute_error.py b/google/ads/googleads/v15/errors/types/customizer_attribute_error.py new file mode 100644 index 000000000..1c5d4359a --- /dev/null +++ b/google/ads/googleads/v15/errors/types/customizer_attribute_error.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_CUSTOMIZER_ATTRIBUTE_NAME = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/database_error.py b/google/ads/googleads/v15/errors/types/database_error.py new file mode 100644 index 000000000..b3f99ea19 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/database_error.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "DatabaseErrorEnum", + }, +) + + +class DatabaseErrorEnum(proto.Message): + r"""Container for enum describing possible database errors.""" + + class DatabaseError(proto.Enum): + r"""Enum describing possible database errors.""" + 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/v15/errors/types/date_error.py b/google/ads/googleads/v15/errors/types/date_error.py new file mode 100644 index 000000000..623a1ebbd --- /dev/null +++ b/google/ads/googleads/v15/errors/types/date_error.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "DateErrorEnum", + }, +) + + +class DateErrorEnum(proto.Message): + r"""Container for enum describing possible date errors.""" + + class DateError(proto.Enum): + r"""Enum describing possible date errors.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/date_range_error.py b/google/ads/googleads/v15/errors/types/date_range_error.py new file mode 100644 index 000000000..a56cd741b --- /dev/null +++ b/google/ads/googleads/v15/errors/types/date_range_error.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/distinct_error.py b/google/ads/googleads/v15/errors/types/distinct_error.py new file mode 100644 index 000000000..fe94d6c75 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/distinct_error.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "DistinctErrorEnum", + }, +) + + +class DistinctErrorEnum(proto.Message): + r"""Container for enum describing possible distinct errors.""" + + class DistinctError(proto.Enum): + r"""Enum describing possible distinct errors.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + DUPLICATE_ELEMENT = 2 + DUPLICATE_TYPE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/enum_error.py b/google/ads/googleads/v15/errors/types/enum_error.py new file mode 100644 index 000000000..e95a46e32 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/enum_error.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "EnumErrorEnum", + }, +) + + +class EnumErrorEnum(proto.Message): + r"""Container for enum describing possible enum errors.""" + + class EnumError(proto.Enum): + r"""Enum describing possible enum errors.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ENUM_VALUE_NOT_PERMITTED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/errors.py b/google/ads/googleads/v15/errors/types/errors.py new file mode 100644 index 000000000..7aa4ef008 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/errors.py @@ -0,0 +1,2387 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import policy +from google.ads.googleads.v15.common.types import value +from google.ads.googleads.v15.enums.types import resource_limit_type +from google.ads.googleads.v15.errors.types import ( + access_invitation_error as gage_access_invitation_error, +) +from google.ads.googleads.v15.errors.types import ( + account_budget_proposal_error as gage_account_budget_proposal_error, +) +from google.ads.googleads.v15.errors.types import ( + account_link_error as gage_account_link_error, +) +from google.ads.googleads.v15.errors.types import ( + ad_customizer_error as gage_ad_customizer_error, +) +from google.ads.googleads.v15.errors.types import ad_error as gage_ad_error +from google.ads.googleads.v15.errors.types import ( + ad_group_ad_error as gage_ad_group_ad_error, +) +from google.ads.googleads.v15.errors.types import ( + ad_group_bid_modifier_error as gage_ad_group_bid_modifier_error, +) +from google.ads.googleads.v15.errors.types import ( + ad_group_criterion_customizer_error as gage_ad_group_criterion_customizer_error, +) +from google.ads.googleads.v15.errors.types import ( + ad_group_criterion_error as gage_ad_group_criterion_error, +) +from google.ads.googleads.v15.errors.types import ( + ad_group_customizer_error as gage_ad_group_customizer_error, +) +from google.ads.googleads.v15.errors.types import ( + ad_group_error as gage_ad_group_error, +) +from google.ads.googleads.v15.errors.types import ( + ad_group_feed_error as gage_ad_group_feed_error, +) +from google.ads.googleads.v15.errors.types import ( + ad_parameter_error as gage_ad_parameter_error, +) +from google.ads.googleads.v15.errors.types import ( + ad_sharing_error as gage_ad_sharing_error, +) +from google.ads.googleads.v15.errors.types import adx_error as gage_adx_error +from google.ads.googleads.v15.errors.types import ( + asset_error as gage_asset_error, +) +from google.ads.googleads.v15.errors.types import ( + asset_group_asset_error as gage_asset_group_asset_error, +) +from google.ads.googleads.v15.errors.types import ( + asset_group_error as gage_asset_group_error, +) +from google.ads.googleads.v15.errors.types import ( + asset_group_listing_group_filter_error as gage_asset_group_listing_group_filter_error, +) +from google.ads.googleads.v15.errors.types import ( + asset_group_signal_error as gage_asset_group_signal_error, +) +from google.ads.googleads.v15.errors.types import ( + asset_link_error as gage_asset_link_error, +) +from google.ads.googleads.v15.errors.types import ( + asset_set_asset_error as gage_asset_set_asset_error, +) +from google.ads.googleads.v15.errors.types import ( + asset_set_error as gage_asset_set_error, +) +from google.ads.googleads.v15.errors.types import ( + asset_set_link_error as gage_asset_set_link_error, +) +from google.ads.googleads.v15.errors.types import ( + audience_error as gage_audience_error, +) +from google.ads.googleads.v15.errors.types import ( + audience_insights_error as gage_audience_insights_error, +) +from google.ads.googleads.v15.errors.types import ( + authentication_error as gage_authentication_error, +) +from google.ads.googleads.v15.errors.types import ( + authorization_error as gage_authorization_error, +) +from google.ads.googleads.v15.errors.types import ( + batch_job_error as gage_batch_job_error, +) +from google.ads.googleads.v15.errors.types import ( + bidding_error as gage_bidding_error, +) +from google.ads.googleads.v15.errors.types import ( + bidding_strategy_error as gage_bidding_strategy_error, +) +from google.ads.googleads.v15.errors.types import ( + billing_setup_error as gage_billing_setup_error, +) +from google.ads.googleads.v15.errors.types import ( + campaign_budget_error as gage_campaign_budget_error, +) +from google.ads.googleads.v15.errors.types import ( + campaign_conversion_goal_error as gage_campaign_conversion_goal_error, +) +from google.ads.googleads.v15.errors.types import ( + campaign_criterion_error as gage_campaign_criterion_error, +) +from google.ads.googleads.v15.errors.types import ( + campaign_customizer_error as gage_campaign_customizer_error, +) +from google.ads.googleads.v15.errors.types import ( + campaign_draft_error as gage_campaign_draft_error, +) +from google.ads.googleads.v15.errors.types import ( + campaign_error as gage_campaign_error, +) +from google.ads.googleads.v15.errors.types import ( + campaign_experiment_error as gage_campaign_experiment_error, +) +from google.ads.googleads.v15.errors.types import ( + campaign_feed_error as gage_campaign_feed_error, +) +from google.ads.googleads.v15.errors.types import ( + campaign_lifecycle_goal_error as gage_campaign_lifecycle_goal_error, +) +from google.ads.googleads.v15.errors.types import ( + campaign_shared_set_error as gage_campaign_shared_set_error, +) +from google.ads.googleads.v15.errors.types import ( + change_event_error as gage_change_event_error, +) +from google.ads.googleads.v15.errors.types import ( + change_status_error as gage_change_status_error, +) +from google.ads.googleads.v15.errors.types import ( + collection_size_error as gage_collection_size_error, +) +from google.ads.googleads.v15.errors.types import ( + context_error as gage_context_error, +) +from google.ads.googleads.v15.errors.types import ( + conversion_action_error as gage_conversion_action_error, +) +from google.ads.googleads.v15.errors.types import ( + conversion_adjustment_upload_error as gage_conversion_adjustment_upload_error, +) +from google.ads.googleads.v15.errors.types import ( + conversion_custom_variable_error as gage_conversion_custom_variable_error, +) +from google.ads.googleads.v15.errors.types import ( + conversion_goal_campaign_config_error as gage_conversion_goal_campaign_config_error, +) +from google.ads.googleads.v15.errors.types import ( + conversion_upload_error as gage_conversion_upload_error, +) +from google.ads.googleads.v15.errors.types import ( + conversion_value_rule_error as gage_conversion_value_rule_error, +) +from google.ads.googleads.v15.errors.types import ( + conversion_value_rule_set_error as gage_conversion_value_rule_set_error, +) +from google.ads.googleads.v15.errors.types import ( + country_code_error as gage_country_code_error, +) +from google.ads.googleads.v15.errors.types import ( + criterion_error as gage_criterion_error, +) +from google.ads.googleads.v15.errors.types import ( + currency_code_error as gage_currency_code_error, +) +from google.ads.googleads.v15.errors.types import ( + currency_error as gage_currency_error, +) +from google.ads.googleads.v15.errors.types import ( + custom_audience_error as gage_custom_audience_error, +) +from google.ads.googleads.v15.errors.types import ( + custom_conversion_goal_error as gage_custom_conversion_goal_error, +) +from google.ads.googleads.v15.errors.types import ( + custom_interest_error as gage_custom_interest_error, +) +from google.ads.googleads.v15.errors.types import ( + customer_client_link_error as gage_customer_client_link_error, +) +from google.ads.googleads.v15.errors.types import ( + customer_customizer_error as gage_customer_customizer_error, +) +from google.ads.googleads.v15.errors.types import ( + customer_error as gage_customer_error, +) +from google.ads.googleads.v15.errors.types import ( + customer_feed_error as gage_customer_feed_error, +) +from google.ads.googleads.v15.errors.types import ( + customer_lifecycle_goal_error as gage_customer_lifecycle_goal_error, +) +from google.ads.googleads.v15.errors.types import ( + customer_manager_link_error as gage_customer_manager_link_error, +) +from google.ads.googleads.v15.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.v15.errors.types import ( + customer_user_access_error as gage_customer_user_access_error, +) +from google.ads.googleads.v15.errors.types import ( + customizer_attribute_error as gage_customizer_attribute_error, +) +from google.ads.googleads.v15.errors.types import ( + database_error as gage_database_error, +) +from google.ads.googleads.v15.errors.types import date_error as gage_date_error +from google.ads.googleads.v15.errors.types import ( + date_range_error as gage_date_range_error, +) +from google.ads.googleads.v15.errors.types import ( + distinct_error as gage_distinct_error, +) +from google.ads.googleads.v15.errors.types import enum_error as gage_enum_error +from google.ads.googleads.v15.errors.types import ( + experiment_arm_error as gage_experiment_arm_error, +) +from google.ads.googleads.v15.errors.types import ( + experiment_error as gage_experiment_error, +) +from google.ads.googleads.v15.errors.types import ( + extension_feed_item_error as gage_extension_feed_item_error, +) +from google.ads.googleads.v15.errors.types import ( + extension_setting_error as gage_extension_setting_error, +) +from google.ads.googleads.v15.errors.types import ( + feed_attribute_reference_error as gage_feed_attribute_reference_error, +) +from google.ads.googleads.v15.errors.types import feed_error as gage_feed_error +from google.ads.googleads.v15.errors.types import ( + feed_item_error as gage_feed_item_error, +) +from google.ads.googleads.v15.errors.types import ( + feed_item_set_error as gage_feed_item_set_error, +) +from google.ads.googleads.v15.errors.types import ( + feed_item_set_link_error as gage_feed_item_set_link_error, +) +from google.ads.googleads.v15.errors.types import ( + feed_item_target_error as gage_feed_item_target_error, +) +from google.ads.googleads.v15.errors.types import ( + feed_item_validation_error as gage_feed_item_validation_error, +) +from google.ads.googleads.v15.errors.types import ( + feed_mapping_error as gage_feed_mapping_error, +) +from google.ads.googleads.v15.errors.types import ( + field_error as gage_field_error, +) +from google.ads.googleads.v15.errors.types import ( + field_mask_error as gage_field_mask_error, +) +from google.ads.googleads.v15.errors.types import ( + function_error as gage_function_error, +) +from google.ads.googleads.v15.errors.types import ( + function_parsing_error as gage_function_parsing_error, +) +from google.ads.googleads.v15.errors.types import ( + geo_target_constant_suggestion_error as gage_geo_target_constant_suggestion_error, +) +from google.ads.googleads.v15.errors.types import ( + header_error as gage_header_error, +) +from google.ads.googleads.v15.errors.types import id_error as gage_id_error +from google.ads.googleads.v15.errors.types import ( + image_error as gage_image_error, +) +from google.ads.googleads.v15.errors.types import ( + internal_error as gage_internal_error, +) +from google.ads.googleads.v15.errors.types import ( + invoice_error as gage_invoice_error, +) +from google.ads.googleads.v15.errors.types import ( + keyword_plan_ad_group_error as gage_keyword_plan_ad_group_error, +) +from google.ads.googleads.v15.errors.types import ( + keyword_plan_ad_group_keyword_error as gage_keyword_plan_ad_group_keyword_error, +) +from google.ads.googleads.v15.errors.types import ( + keyword_plan_campaign_error as gage_keyword_plan_campaign_error, +) +from google.ads.googleads.v15.errors.types import ( + keyword_plan_campaign_keyword_error as gage_keyword_plan_campaign_keyword_error, +) +from google.ads.googleads.v15.errors.types import ( + keyword_plan_error as gage_keyword_plan_error, +) +from google.ads.googleads.v15.errors.types import ( + keyword_plan_idea_error as gage_keyword_plan_idea_error, +) +from google.ads.googleads.v15.errors.types import ( + label_error as gage_label_error, +) +from google.ads.googleads.v15.errors.types import ( + language_code_error as gage_language_code_error, +) +from google.ads.googleads.v15.errors.types import ( + list_operation_error as gage_list_operation_error, +) +from google.ads.googleads.v15.errors.types import ( + manager_link_error as gage_manager_link_error, +) +from google.ads.googleads.v15.errors.types import ( + media_bundle_error as gage_media_bundle_error, +) +from google.ads.googleads.v15.errors.types import ( + media_file_error as gage_media_file_error, +) +from google.ads.googleads.v15.errors.types import ( + media_upload_error as gage_media_upload_error, +) +from google.ads.googleads.v15.errors.types import ( + merchant_center_error as gage_merchant_center_error, +) +from google.ads.googleads.v15.errors.types import ( + multiplier_error as gage_multiplier_error, +) +from google.ads.googleads.v15.errors.types import ( + mutate_error as gage_mutate_error, +) +from google.ads.googleads.v15.errors.types import ( + new_resource_creation_error as gage_new_resource_creation_error, +) +from google.ads.googleads.v15.errors.types import ( + not_allowlisted_error as gage_not_allowlisted_error, +) +from google.ads.googleads.v15.errors.types import ( + not_empty_error as gage_not_empty_error, +) +from google.ads.googleads.v15.errors.types import null_error as gage_null_error +from google.ads.googleads.v15.errors.types import ( + offline_user_data_job_error as gage_offline_user_data_job_error, +) +from google.ads.googleads.v15.errors.types import ( + operation_access_denied_error as gage_operation_access_denied_error, +) +from google.ads.googleads.v15.errors.types import ( + operator_error as gage_operator_error, +) +from google.ads.googleads.v15.errors.types import ( + partial_failure_error as gage_partial_failure_error, +) +from google.ads.googleads.v15.errors.types import ( + payments_account_error as gage_payments_account_error, +) +from google.ads.googleads.v15.errors.types import ( + policy_finding_error as gage_policy_finding_error, +) +from google.ads.googleads.v15.errors.types import ( + policy_validation_parameter_error as gage_policy_validation_parameter_error, +) +from google.ads.googleads.v15.errors.types import ( + policy_violation_error as gage_policy_violation_error, +) +from google.ads.googleads.v15.errors.types import ( + product_link_error as gage_product_link_error, +) +from google.ads.googleads.v15.errors.types import ( + product_link_invitation_error as gage_product_link_invitation_error, +) +from google.ads.googleads.v15.errors.types import ( + query_error as gage_query_error, +) +from google.ads.googleads.v15.errors.types import ( + quota_error as gage_quota_error, +) +from google.ads.googleads.v15.errors.types import ( + range_error as gage_range_error, +) +from google.ads.googleads.v15.errors.types import ( + reach_plan_error as gage_reach_plan_error, +) +from google.ads.googleads.v15.errors.types import ( + recommendation_error as gage_recommendation_error, +) +from google.ads.googleads.v15.errors.types import ( + recommendation_subscription_error as gage_recommendation_subscription_error, +) +from google.ads.googleads.v15.errors.types import ( + region_code_error as gage_region_code_error, +) +from google.ads.googleads.v15.errors.types import ( + request_error as gage_request_error, +) +from google.ads.googleads.v15.errors.types import ( + resource_access_denied_error as gage_resource_access_denied_error, +) +from google.ads.googleads.v15.errors.types import ( + resource_count_limit_exceeded_error as gage_resource_count_limit_exceeded_error, +) +from google.ads.googleads.v15.errors.types import ( + search_term_insight_error as gage_search_term_insight_error, +) +from google.ads.googleads.v15.errors.types import ( + setting_error as gage_setting_error, +) +from google.ads.googleads.v15.errors.types import ( + shared_criterion_error as gage_shared_criterion_error, +) +from google.ads.googleads.v15.errors.types import ( + shared_set_error as gage_shared_set_error, +) +from google.ads.googleads.v15.errors.types import ( + size_limit_error as gage_size_limit_error, +) +from google.ads.googleads.v15.errors.types import ( + smart_campaign_error as gage_smart_campaign_error, +) +from google.ads.googleads.v15.errors.types import ( + string_format_error as gage_string_format_error, +) +from google.ads.googleads.v15.errors.types import ( + string_length_error as gage_string_length_error, +) +from google.ads.googleads.v15.errors.types import ( + third_party_app_analytics_link_error as gage_third_party_app_analytics_link_error, +) +from google.ads.googleads.v15.errors.types import ( + time_zone_error as gage_time_zone_error, +) +from google.ads.googleads.v15.errors.types import ( + url_field_error as gage_url_field_error, +) +from google.ads.googleads.v15.errors.types import ( + user_data_error as gage_user_data_error, +) +from google.ads.googleads.v15.errors.types import ( + user_list_error as gage_user_list_error, +) +from google.ads.googleads.v15.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.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "GoogleAdsFailure", + "GoogleAdsError", + "ErrorCode", + "ErrorLocation", + "ErrorDetails", + "PolicyViolationDetails", + "PolicyFindingDetails", + "QuotaErrorDetails", + "ResourceCountDetails", + }, +) + + +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.v15.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.v15.errors.types.ErrorCode): + An enum value that indicates which error + occurred. + message (str): + A human-readable description of the error. + trigger (google.ads.googleads.v15.common.types.Value): + The value that triggered the error. + location (google.ads.googleads.v15.errors.types.ErrorLocation): + Describes the part of the request proto that + caused the error. + details (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.errors.types.ListOperationErrorEnum.ListOperationError): + An error with a list operation. + + This field is a member of `oneof`_ ``error_code``. + query_error (google.ads.googleads.v15.errors.types.QueryErrorEnum.QueryError): + An error with an AWQL query + + This field is a member of `oneof`_ ``error_code``. + mutate_error (google.ads.googleads.v15.errors.types.MutateErrorEnum.MutateError): + An error with a mutate + + This field is a member of `oneof`_ ``error_code``. + field_mask_error (google.ads.googleads.v15.errors.types.FieldMaskErrorEnum.FieldMaskError): + An error with a field mask + + This field is a member of `oneof`_ ``error_code``. + authorization_error (google.ads.googleads.v15.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.v15.errors.types.InternalErrorEnum.InternalError): + An unexpected server-side error. + + This field is a member of `oneof`_ ``error_code``. + quota_error (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.errors.types.CampaignErrorEnum.CampaignError): + An error with a Campaign mutate. + + This field is a member of `oneof`_ ``error_code``. + authentication_error (google.ads.googleads.v15.errors.types.AuthenticationErrorEnum.AuthenticationError): + Indicates failure to properly authenticate + user. + + This field is a member of `oneof`_ ``error_code``. + ad_group_criterion_customizer_error (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.errors.types.AdxErrorEnum.AdxError): + The reasons for the adx error + + This field is a member of `oneof`_ ``error_code``. + asset_error (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.errors.types.FeedAttributeReferenceErrorEnum.FeedAttributeReferenceError): + The reasons for the feed attribute reference + error + + This field is a member of `oneof`_ ``error_code``. + function_error (google.ads.googleads.v15.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.v15.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.v15.errors.types.IdErrorEnum.IdError): + The reasons for the id error + + This field is a member of `oneof`_ ``error_code``. + image_error (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.errors.types.NullErrorEnum.NullError): + The reasons for the null error + + This field is a member of `oneof`_ ``error_code``. + operator_error (google.ads.googleads.v15.errors.types.OperatorErrorEnum.OperatorError): + The reasons for the operator error + + This field is a member of `oneof`_ ``error_code``. + range_error (google.ads.googleads.v15.errors.types.RangeErrorEnum.RangeError): + The reasons for the range error + + This field is a member of `oneof`_ ``error_code``. + recommendation_error (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.errors.types.ContextErrorEnum.ContextError): + The reasons for the context error + + This field is a member of `oneof`_ ``error_code``. + field_error (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.errors.types.HeaderErrorEnum.HeaderError): + The reasons for the header error. + + This field is a member of `oneof`_ ``error_code``. + database_error (google.ads.googleads.v15.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.v15.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.v15.errors.types.EnumErrorEnum.EnumError): + The reason for enum error. + + This field is a member of `oneof`_ ``error_code``. + keyword_plan_error (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.errors.types.PartialFailureErrorEnum.PartialFailureError): + The reasons for the mutate job error + + This field is a member of `oneof`_ ``error_code``. + policy_validation_parameter_error (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.errors.types.ProductLinkErrorEnum.ProductLinkError): + The reasons for the product link error + + This field is a member of `oneof`_ ``error_code``. + customer_sk_ad_network_conversion_value_schema_error (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.errors.types.CampaignLifecycleGoalErrorEnum.CampaignLifecycleGoalError): + The reasons for the campaign lifecycle goal + 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, + ) + ) + authentication_error: gage_authentication_error.AuthenticationErrorEnum.AuthenticationError = proto.Field( + proto.ENUM, + number=17, + oneof="error_code", + enum=gage_authentication_error.AuthenticationErrorEnum.AuthenticationError, + ) + 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, + ) + 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, + ) + 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, + ) + 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, + ) + + +class ErrorLocation(proto.Message): + r"""Describes the part of the request proto that caused the + error. + + Attributes: + field_path_elements (MutableSequence[google.ads.googleads.v15.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.v15.errors.types.PolicyViolationDetails): + Describes an ad policy violation. + policy_finding_details (google.ads.googleads.v15.errors.types.PolicyFindingDetails): + Describes policy violation findings. + quota_error_details (google.ads.googleads.v15.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.v15.errors.types.ResourceCountDetails): + Details for a resource count limit exceeded + 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", + ) + + +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.v15.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.v15.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.v15.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.""" + 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.v15.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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/experiment_arm_error.py b/google/ads/googleads/v15/errors/types/experiment_arm_error.py new file mode 100644 index 000000000..4d8051719 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/experiment_arm_error.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/experiment_error.py b/google/ads/googleads/v15/errors/types/experiment_error.py new file mode 100644 index 000000000..f96ae4412 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/experiment_error.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "ExperimentErrorEnum", + }, +) + + +class ExperimentErrorEnum(proto.Message): + r"""Container for enum describing possible experiment error.""" + + class ExperimentError(proto.Enum): + r"""Enum describing possible experiment errors.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/extension_feed_item_error.py b/google/ads/googleads/v15/errors/types/extension_feed_item_error.py new file mode 100644 index 000000000..bb990c02c --- /dev/null +++ b/google/ads/googleads/v15/errors/types/extension_feed_item_error.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/extension_setting_error.py b/google/ads/googleads/v15/errors/types/extension_setting_error.py new file mode 100644 index 000000000..a873e4fcb --- /dev/null +++ b/google/ads/googleads/v15/errors/types/extension_setting_error.py @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/feed_attribute_reference_error.py b/google/ads/googleads/v15/errors/types/feed_attribute_reference_error.py new file mode 100644 index 000000000..bf975d5cc --- /dev/null +++ b/google/ads/googleads/v15/errors/types/feed_attribute_reference_error.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/feed_error.py b/google/ads/googleads/v15/errors/types/feed_error.py new file mode 100644 index 000000000..f81fdd5f9 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/feed_error.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "FeedErrorEnum", + }, +) + + +class FeedErrorEnum(proto.Message): + r"""Container for enum describing possible feed errors.""" + + class FeedError(proto.Enum): + r"""Enum describing possible feed errors.""" + 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/v15/errors/types/feed_item_error.py b/google/ads/googleads/v15/errors/types/feed_item_error.py new file mode 100644 index 000000000..1939cd15f --- /dev/null +++ b/google/ads/googleads/v15/errors/types/feed_item_error.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/feed_item_set_error.py b/google/ads/googleads/v15/errors/types/feed_item_set_error.py new file mode 100644 index 000000000..ed36d6988 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/feed_item_set_error.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/feed_item_set_link_error.py b/google/ads/googleads/v15/errors/types/feed_item_set_link_error.py new file mode 100644 index 000000000..2e6635a30 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/feed_item_set_link_error.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/feed_item_target_error.py b/google/ads/googleads/v15/errors/types/feed_item_target_error.py new file mode 100644 index 000000000..3dfdc249d --- /dev/null +++ b/google/ads/googleads/v15/errors/types/feed_item_target_error.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/feed_item_validation_error.py b/google/ads/googleads/v15/errors/types/feed_item_validation_error.py new file mode 100644 index 000000000..567273e09 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/feed_item_validation_error.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/feed_mapping_error.py b/google/ads/googleads/v15/errors/types/feed_mapping_error.py new file mode 100644 index 000000000..c2d5f8c5f --- /dev/null +++ b/google/ads/googleads/v15/errors/types/feed_mapping_error.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/field_error.py b/google/ads/googleads/v15/errors/types/field_error.py new file mode 100644 index 000000000..9237275c5 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/field_error.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "FieldErrorEnum", + }, +) + + +class FieldErrorEnum(proto.Message): + r"""Container for enum describing possible field errors.""" + + class FieldError(proto.Enum): + r"""Enum describing possible field errors.""" + 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/v15/errors/types/field_mask_error.py b/google/ads/googleads/v15/errors/types/field_mask_error.py new file mode 100644 index 000000000..b7129197d --- /dev/null +++ b/google/ads/googleads/v15/errors/types/field_mask_error.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/function_error.py b/google/ads/googleads/v15/errors/types/function_error.py new file mode 100644 index 000000000..e892358dc --- /dev/null +++ b/google/ads/googleads/v15/errors/types/function_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "FunctionErrorEnum", + }, +) + + +class FunctionErrorEnum(proto.Message): + r"""Container for enum describing possible function errors.""" + + class FunctionError(proto.Enum): + r"""Enum describing possible function errors.""" + 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/v15/errors/types/function_parsing_error.py b/google/ads/googleads/v15/errors/types/function_parsing_error.py new file mode 100644 index 000000000..d1f5afb48 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/function_parsing_error.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/geo_target_constant_suggestion_error.py b/google/ads/googleads/v15/errors/types/geo_target_constant_suggestion_error.py new file mode 100644 index 000000000..222f3cab6 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/geo_target_constant_suggestion_error.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/errors/types/header_error.py b/google/ads/googleads/v15/errors/types/header_error.py new file mode 100644 index 000000000..fa68603a9 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/header_error.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "HeaderErrorEnum", + }, +) + + +class HeaderErrorEnum(proto.Message): + r"""Container for enum describing possible header errors.""" + + class HeaderError(proto.Enum): + r"""Enum describing possible header errors.""" + 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/v15/errors/types/id_error.py b/google/ads/googleads/v15/errors/types/id_error.py new file mode 100644 index 000000000..6d67c6121 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/id_error.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "IdErrorEnum", + }, +) + + +class IdErrorEnum(proto.Message): + r"""Container for enum describing possible ID errors.""" + + class IdError(proto.Enum): + r"""Enum describing possible ID errors.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + NOT_FOUND = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/image_error.py b/google/ads/googleads/v15/errors/types/image_error.py new file mode 100644 index 000000000..5b65d84bd --- /dev/null +++ b/google/ads/googleads/v15/errors/types/image_error.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "ImageErrorEnum", + }, +) + + +class ImageErrorEnum(proto.Message): + r"""Container for enum describing possible image errors.""" + + class ImageError(proto.Enum): + r"""Enum describing possible image errors.""" + 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/v15/errors/types/internal_error.py b/google/ads/googleads/v15/errors/types/internal_error.py new file mode 100644 index 000000000..3e8677ec8 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/internal_error.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "InternalErrorEnum", + }, +) + + +class InternalErrorEnum(proto.Message): + r"""Container for enum describing possible internal errors.""" + + class InternalError(proto.Enum): + r"""Enum describing possible internal errors.""" + 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/v15/errors/types/invoice_error.py b/google/ads/googleads/v15/errors/types/invoice_error.py new file mode 100644 index 000000000..45d8aa054 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/invoice_error.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "InvoiceErrorEnum", + }, +) + + +class InvoiceErrorEnum(proto.Message): + r"""Container for enum describing possible invoice errors.""" + + class InvoiceError(proto.Enum): + r"""Enum describing possible invoice errors.""" + 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/v15/errors/types/keyword_plan_ad_group_error.py b/google/ads/googleads/v15/errors/types/keyword_plan_ad_group_error.py new file mode 100644 index 000000000..ce8f1592e --- /dev/null +++ b/google/ads/googleads/v15/errors/types/keyword_plan_ad_group_error.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_NAME = 2 + DUPLICATE_NAME = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/keyword_plan_ad_group_keyword_error.py b/google/ads/googleads/v15/errors/types/keyword_plan_ad_group_keyword_error.py new file mode 100644 index 000000000..b8a0bbd4a --- /dev/null +++ b/google/ads/googleads/v15/errors/types/keyword_plan_ad_group_keyword_error.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/errors/types/keyword_plan_campaign_error.py b/google/ads/googleads/v15/errors/types/keyword_plan_campaign_error.py new file mode 100644 index 000000000..7ce678310 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/keyword_plan_campaign_error.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/errors/types/keyword_plan_campaign_keyword_error.py b/google/ads/googleads/v15/errors/types/keyword_plan_campaign_keyword_error.py new file mode 100644 index 000000000..5b28e2d64 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/keyword_plan_campaign_keyword_error.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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. + """ + UNSPECIFIED = 0 + UNKNOWN = 1 + CAMPAIGN_KEYWORD_IS_POSITIVE = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/keyword_plan_error.py b/google/ads/googleads/v15/errors/types/keyword_plan_error.py new file mode 100644 index 000000000..716dc1630 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/keyword_plan_error.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/keyword_plan_idea_error.py b/google/ads/googleads/v15/errors/types/keyword_plan_idea_error.py new file mode 100644 index 000000000..f403bd5a2 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/keyword_plan_idea_error.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + URL_CRAWL_ERROR = 2 + INVALID_VALUE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/label_error.py b/google/ads/googleads/v15/errors/types/label_error.py new file mode 100644 index 000000000..4c30d432d --- /dev/null +++ b/google/ads/googleads/v15/errors/types/label_error.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "LabelErrorEnum", + }, +) + + +class LabelErrorEnum(proto.Message): + r"""Container for enum describing possible label errors.""" + + class LabelError(proto.Enum): + r"""Enum describing possible label errors.""" + 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/v15/errors/types/language_code_error.py b/google/ads/googleads/v15/errors/types/language_code_error.py new file mode 100644 index 000000000..2a2a14287 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/language_code_error.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "LanguageCodeErrorEnum", + }, +) + + +class LanguageCodeErrorEnum(proto.Message): + r"""Container for enum describing language code errors.""" + + class LanguageCodeError(proto.Enum): + r"""Enum describing language code errors.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + LANGUAGE_CODE_NOT_FOUND = 2 + INVALID_LANGUAGE_CODE = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/list_operation_error.py b/google/ads/googleads/v15/errors/types/list_operation_error.py new file mode 100644 index 000000000..24d27ce6d --- /dev/null +++ b/google/ads/googleads/v15/errors/types/list_operation_error.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + REQUIRED_FIELD_MISSING = 7 + DUPLICATE_VALUES = 8 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/manager_link_error.py b/google/ads/googleads/v15/errors/types/manager_link_error.py new file mode 100644 index 000000000..3422369fe --- /dev/null +++ b/google/ads/googleads/v15/errors/types/manager_link_error.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "ManagerLinkErrorEnum", + }, +) + + +class ManagerLinkErrorEnum(proto.Message): + r"""Container for enum describing possible ManagerLink errors.""" + + class ManagerLinkError(proto.Enum): + r"""Enum describing possible ManagerLink errors.""" + 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/v15/errors/types/media_bundle_error.py b/google/ads/googleads/v15/errors/types/media_bundle_error.py new file mode 100644 index 000000000..817a116ea --- /dev/null +++ b/google/ads/googleads/v15/errors/types/media_bundle_error.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/media_file_error.py b/google/ads/googleads/v15/errors/types/media_file_error.py new file mode 100644 index 000000000..993280bd9 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/media_file_error.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/media_upload_error.py b/google/ads/googleads/v15/errors/types/media_upload_error.py new file mode 100644 index 000000000..e6e8dba42 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/media_upload_error.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/merchant_center_error.py b/google/ads/googleads/v15/errors/types/merchant_center_error.py new file mode 100644 index 000000000..2c822e569 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/merchant_center_error.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/multiplier_error.py b/google/ads/googleads/v15/errors/types/multiplier_error.py new file mode 100644 index 000000000..2ff3c0414 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/multiplier_error.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "MultiplierErrorEnum", + }, +) + + +class MultiplierErrorEnum(proto.Message): + r"""Container for enum describing possible multiplier errors.""" + + class MultiplierError(proto.Enum): + r"""Enum describing possible multiplier errors.""" + 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/v15/errors/types/mutate_error.py b/google/ads/googleads/v15/errors/types/mutate_error.py new file mode 100644 index 000000000..d0e3f1e2e --- /dev/null +++ b/google/ads/googleads/v15/errors/types/mutate_error.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "MutateErrorEnum", + }, +) + + +class MutateErrorEnum(proto.Message): + r"""Container for enum describing possible mutate errors.""" + + class MutateError(proto.Enum): + r"""Enum describing possible mutate errors.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/new_resource_creation_error.py b/google/ads/googleads/v15/errors/types/new_resource_creation_error.py new file mode 100644 index 000000000..c2248a904 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/new_resource_creation_error.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/not_allowlisted_error.py b/google/ads/googleads/v15/errors/types/not_allowlisted_error.py new file mode 100644 index 000000000..d340671a9 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/not_allowlisted_error.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CUSTOMER_NOT_ALLOWLISTED_FOR_THIS_FEATURE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/not_empty_error.py b/google/ads/googleads/v15/errors/types/not_empty_error.py new file mode 100644 index 000000000..6b17a69e3 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/not_empty_error.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + EMPTY_LIST = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/null_error.py b/google/ads/googleads/v15/errors/types/null_error.py new file mode 100644 index 000000000..d38601e4c --- /dev/null +++ b/google/ads/googleads/v15/errors/types/null_error.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "NullErrorEnum", + }, +) + + +class NullErrorEnum(proto.Message): + r"""Container for enum describing possible null errors.""" + + class NullError(proto.Enum): + r"""Enum describing possible null errors.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + NULL_CONTENT = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/offline_user_data_job_error.py b/google/ads/googleads/v15/errors/types/offline_user_data_job_error.py new file mode 100644 index 000000000..ae53a8b6f --- /dev/null +++ b/google/ads/googleads/v15/errors/types/offline_user_data_job_error.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/operation_access_denied_error.py b/google/ads/googleads/v15/errors/types/operation_access_denied_error.py new file mode 100644 index 000000000..60a28980e --- /dev/null +++ b/google/ads/googleads/v15/errors/types/operation_access_denied_error.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/operator_error.py b/google/ads/googleads/v15/errors/types/operator_error.py new file mode 100644 index 000000000..ef4cd5a57 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/operator_error.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "OperatorErrorEnum", + }, +) + + +class OperatorErrorEnum(proto.Message): + r"""Container for enum describing possible operator errors.""" + + class OperatorError(proto.Enum): + r"""Enum describing possible operator errors.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + OPERATOR_NOT_SUPPORTED = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/partial_failure_error.py b/google/ads/googleads/v15/errors/types/partial_failure_error.py new file mode 100644 index 000000000..f7aaa9267 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/partial_failure_error.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + PARTIAL_FAILURE_MODE_REQUIRED = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/payments_account_error.py b/google/ads/googleads/v15/errors/types/payments_account_error.py new file mode 100644 index 000000000..be61a79e9 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/payments_account_error.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + NOT_SUPPORTED_FOR_MANAGER_CUSTOMER = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/policy_finding_error.py b/google/ads/googleads/v15/errors/types/policy_finding_error.py new file mode 100644 index 000000000..2bd4f491b --- /dev/null +++ b/google/ads/googleads/v15/errors/types/policy_finding_error.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + POLICY_FINDING = 2 + POLICY_TOPIC_NOT_FOUND = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/policy_validation_parameter_error.py b/google/ads/googleads/v15/errors/types/policy_validation_parameter_error.py new file mode 100644 index 000000000..f79b6bc7a --- /dev/null +++ b/google/ads/googleads/v15/errors/types/policy_validation_parameter_error.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/policy_violation_error.py b/google/ads/googleads/v15/errors/types/policy_violation_error.py new file mode 100644 index 000000000..2ef6ffc7d --- /dev/null +++ b/google/ads/googleads/v15/errors/types/policy_violation_error.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + POLICY_ERROR = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/product_link_error.py b/google/ads/googleads/v15/errors/types/product_link_error.py new file mode 100644 index 000000000..0999144d6 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/product_link_error.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "ProductLinkErrorEnum", + }, +) + + +class ProductLinkErrorEnum(proto.Message): + r"""Container for enum describing possible ProductLink errors.""" + + class ProductLinkError(proto.Enum): + r"""Enum describing possible ProductLink errors.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_OPERATION = 2 + CREATION_NOT_PERMITTED = 3 + INVITATION_EXISTS = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/product_link_invitation_error.py b/google/ads/googleads/v15/errors/types/product_link_invitation_error.py new file mode 100644 index 000000000..7d3544788 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/product_link_invitation_error.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_STATUS = 2 + PERMISSION_DENIED = 3 + NO_INVITATION_REQUIRED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/query_error.py b/google/ads/googleads/v15/errors/types/query_error.py new file mode 100644 index 000000000..6d96b9360 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/query_error.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "QueryErrorEnum", + }, +) + + +class QueryErrorEnum(proto.Message): + r"""Container for enum describing possible query errors.""" + + class QueryError(proto.Enum): + r"""Enum describing possible query errors.""" + 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 + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/quota_error.py b/google/ads/googleads/v15/errors/types/quota_error.py new file mode 100644 index 000000000..f663c35d0 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/quota_error.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "QuotaErrorEnum", + }, +) + + +class QuotaErrorEnum(proto.Message): + r"""Container for enum describing possible quota errors.""" + + class QuotaError(proto.Enum): + r"""Enum describing possible quota errors.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + RESOURCE_EXHAUSTED = 2 + ACCESS_PROHIBITED = 3 + RESOURCE_TEMPORARILY_EXHAUSTED = 4 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/range_error.py b/google/ads/googleads/v15/errors/types/range_error.py new file mode 100644 index 000000000..ec74589bc --- /dev/null +++ b/google/ads/googleads/v15/errors/types/range_error.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "RangeErrorEnum", + }, +) + + +class RangeErrorEnum(proto.Message): + r"""Container for enum describing possible range errors.""" + + class RangeError(proto.Enum): + r"""Enum describing possible range errors.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + TOO_LOW = 2 + TOO_HIGH = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/reach_plan_error.py b/google/ads/googleads/v15/errors/types/reach_plan_error.py new file mode 100644 index 000000000..991b48b10 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/reach_plan_error.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/recommendation_error.py b/google/ads/googleads/v15/errors/types/recommendation_error.py new file mode 100644 index 000000000..216ef7667 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/recommendation_error.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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. + """ + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/recommendation_subscription_error.py b/google/ads/googleads/v15/errors/types/recommendation_subscription_error.py new file mode 100644 index 000000000..65d613c95 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/recommendation_subscription_error.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/region_code_error.py b/google/ads/googleads/v15/errors/types/region_code_error.py new file mode 100644 index 000000000..8801cd8a7 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/region_code_error.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_REGION_CODE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/request_error.py b/google/ads/googleads/v15/errors/types/request_error.py new file mode 100644 index 000000000..a674462bf --- /dev/null +++ b/google/ads/googleads/v15/errors/types/request_error.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "RequestErrorEnum", + }, +) + + +class RequestErrorEnum(proto.Message): + r"""Container for enum describing possible request errors.""" + + class RequestError(proto.Enum): + r"""Enum describing possible request errors.""" + 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 + REQUIRED_FIELD_MISSING = 9 + IMMUTABLE_FIELD = 11 + TOO_MANY_MUTATE_OPERATIONS = 13 + 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/v15/errors/types/resource_access_denied_error.py b/google/ads/googleads/v15/errors/types/resource_access_denied_error.py new file mode 100644 index 000000000..1b9b24310 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/resource_access_denied_error.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + WRITE_ACCESS_DENIED = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/resource_count_limit_exceeded_error.py b/google/ads/googleads/v15/errors/types/resource_count_limit_exceeded_error.py new file mode 100644 index 000000000..807efb061 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/resource_count_limit_exceeded_error.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/errors/types/search_term_insight_error.py b/google/ads/googleads/v15/errors/types/search_term_insight_error.py new file mode 100644 index 000000000..b5237f207 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/search_term_insight_error.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/setting_error.py b/google/ads/googleads/v15/errors/types/setting_error.py new file mode 100644 index 000000000..9c942dcef --- /dev/null +++ b/google/ads/googleads/v15/errors/types/setting_error.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + manifest={ + "SettingErrorEnum", + }, +) + + +class SettingErrorEnum(proto.Message): + r"""Container for enum describing possible setting errors.""" + + class SettingError(proto.Enum): + r"""Enum describing possible setting errors.""" + 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/v15/errors/types/shared_criterion_error.py b/google/ads/googleads/v15/errors/types/shared_criterion_error.py new file mode 100644 index 000000000..cc256408d --- /dev/null +++ b/google/ads/googleads/v15/errors/types/shared_criterion_error.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + CRITERION_TYPE_NOT_ALLOWED_FOR_SHARED_SET_TYPE = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/shared_set_error.py b/google/ads/googleads/v15/errors/types/shared_set_error.py new file mode 100644 index 000000000..f69064b6e --- /dev/null +++ b/google/ads/googleads/v15/errors/types/shared_set_error.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/size_limit_error.py b/google/ads/googleads/v15/errors/types/size_limit_error.py new file mode 100644 index 000000000..61ee15774 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/size_limit_error.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/smart_campaign_error.py b/google/ads/googleads/v15/errors/types/smart_campaign_error.py new file mode 100644 index 000000000..8c76fc92a --- /dev/null +++ b/google/ads/googleads/v15/errors/types/smart_campaign_error.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/string_format_error.py b/google/ads/googleads/v15/errors/types/string_format_error.py new file mode 100644 index 000000000..a5fa174a0 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/string_format_error.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ILLEGAL_CHARS = 2 + INVALID_FORMAT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/string_length_error.py b/google/ads/googleads/v15/errors/types/string_length_error.py new file mode 100644 index 000000000..f8c64701e --- /dev/null +++ b/google/ads/googleads/v15/errors/types/string_length_error.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + EMPTY = 4 + TOO_SHORT = 2 + TOO_LONG = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/third_party_app_analytics_link_error.py b/google/ads/googleads/v15/errors/types/third_party_app_analytics_link_error.py new file mode 100644 index 000000000..b8298a1e1 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/third_party_app_analytics_link_error.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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. + """ + 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/v15/errors/types/time_zone_error.py b/google/ads/googleads/v15/errors/types/time_zone_error.py new file mode 100644 index 000000000..d4b7c11f1 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/time_zone_error.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + INVALID_TIME_ZONE = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/url_field_error.py b/google/ads/googleads/v15/errors/types/url_field_error.py new file mode 100644 index 000000000..2e9b0658d --- /dev/null +++ b/google/ads/googleads/v15/errors/types/url_field_error.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/user_data_error.py b/google/ads/googleads/v15/errors/types/user_data_error.py new file mode 100644 index 000000000..9839b76e8 --- /dev/null +++ b/google/ads/googleads/v15/errors/types/user_data_error.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/errors/types/user_list_error.py b/google/ads/googleads/v15/errors/types/user_list_error.py new file mode 100644 index 000000000..172bfe53d --- /dev/null +++ b/google/ads/googleads/v15/errors/types/user_list_error.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/errors/types/youtube_video_registration_error.py b/google/ads/googleads/v15/errors/types/youtube_video_registration_error.py new file mode 100644 index 000000000..aad2e71ea --- /dev/null +++ b/google/ads/googleads/v15/errors/types/youtube_video_registration_error.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.errors", + marshal="google.ads.googleads.v15", + 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.""" + 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/v15/resources/__init__.py b/google/ads/googleads/v15/resources/__init__.py new file mode 100644 index 000000000..bcc83b908 --- /dev/null +++ b/google/ads/googleads/v15/resources/__init__.py @@ -0,0 +1,245 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +__all__ = ( + "AccessibleBiddingStrategy", + "AccountBudget", + "AccountBudgetProposal", + "AccountLink", + "Ad", + "AdGroup", + "AdGroupAd", + "AdGroupAdAssetCombinationView", + "AdGroupAdAssetPolicySummary", + "AdGroupAdAssetView", + "AdGroupAdLabel", + "AdGroupAdPolicySummary", + "AdGroupAsset", + "AdGroupAssetSet", + "AdGroupAudienceView", + "AdGroupBidModifier", + "AdGroupCriterion", + "AdGroupCriterionCustomizer", + "AdGroupCriterionLabel", + "AdGroupCriterionSimulation", + "AdGroupCustomizer", + "AdGroupExtensionSetting", + "AdGroupFeed", + "AdGroupLabel", + "AdGroupSimulation", + "AdParameter", + "AdScheduleView", + "AdvertisingPartnerLinkIdentifier", + "AgeRangeView", + "AndroidPrivacySharedKeyGoogleAdGroup", + "AndroidPrivacySharedKeyGoogleCampaign", + "AndroidPrivacySharedKeyGoogleNetworkType", + "Asset", + "AssetFieldTypePolicySummary", + "AssetFieldTypeView", + "AssetGroup", + "AssetGroupAsset", + "AssetGroupAssetCombinationData", + "AssetGroupListingGroupFilter", + "AssetGroupProductGroupView", + "AssetGroupSignal", + "AssetGroupTopCombinationView", + "AssetPolicySummary", + "AssetSet", + "AssetSetAsset", + "AssetSetTypeView", + "AttributeFieldMapping", + "Audience", + "BackgroundCheckVerificationArtifact", + "BatchJob", + "BiddingDataExclusion", + "BiddingSeasonalityAdjustment", + "BiddingStrategy", + "BiddingStrategySimulation", + "BillingSetup", + "CallReportingSetting", + "CallView", + "Campaign", + "CampaignAsset", + "CampaignAssetSet", + "CampaignAudienceView", + "CampaignBidModifier", + "CampaignBudget", + "CampaignConversionGoal", + "CampaignCriterion", + "CampaignCustomizer", + "CampaignDraft", + "CampaignExtensionSetting", + "CampaignFeed", + "CampaignGroup", + "CampaignLabel", + "CampaignLifecycleGoal", + "CampaignSearchTermInsight", + "CampaignSharedSet", + "CampaignSimulation", + "CarrierConstant", + "ChangeEvent", + "ChangeStatus", + "ClickView", + "CombinedAudience", + "ContactDetails", + "ConversionAction", + "ConversionCustomVariable", + "ConversionGoalCampaignConfig", + "ConversionTrackingSetting", + "ConversionValueRule", + "ConversionValueRuleSet", + "CurrencyConstant", + "CustomAudience", + "CustomAudienceMember", + "CustomConversionGoal", + "CustomInterest", + "CustomInterestMember", + "CustomLeadFormSubmissionField", + "Customer", + "CustomerAcquisitionGoalSettings", + "CustomerAgreementSetting", + "CustomerAsset", + "CustomerAssetSet", + "CustomerClient", + "CustomerClientLink", + "CustomerConversionGoal", + "CustomerCustomizer", + "CustomerExtensionSetting", + "CustomerFeed", + "CustomerLabel", + "CustomerLifecycleGoal", + "CustomerManagerLink", + "CustomerNegativeCriterion", + "CustomerSearchTermInsight", + "CustomerSkAdNetworkConversionValueSchema", + "CustomerUserAccess", + "CustomerUserAccessInvitation", + "CustomizerAttribute", + "DataPartnerIdentifier", + "DataPartnerLinkIdentifier", + "DetailPlacementView", + "DetailedDemographic", + "DisplayKeywordView", + "DistanceView", + "DomainCategory", + "DynamicSearchAdsSearchTermView", + "ExpandedLandingPageView", + "Experiment", + "ExperimentArm", + "ExtensionFeedItem", + "Feed", + "FeedAttribute", + "FeedAttributeOperation", + "FeedItem", + "FeedItemAttributeValue", + "FeedItemPlaceholderPolicyInfo", + "FeedItemSet", + "FeedItemSetLink", + "FeedItemTarget", + "FeedItemValidationError", + "FeedMapping", + "FeedPlaceholderView", + "GenderView", + "GeoTargetConstant", + "GeographicView", + "GoogleAdsField", + "GoogleAdsIdentifier", + "GoogleAdsLinkIdentifier", + "GranularInsuranceStatus", + "GranularLicenseStatus", + "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", + "LocalServicesLead", + "LocalServicesLeadConversation", + "LocalServicesSettings", + "LocalServicesVerificationArtifact", + "LocationView", + "ManagedPlacementView", + "MediaAudio", + "MediaBundle", + "MediaFile", + "MediaImage", + "MediaVideo", + "MerchantCenterIdentifier", + "MerchantCenterLinkInvitationIdentifier", + "MessageDetails", + "MobileAppCategoryConstant", + "MobileDeviceConstant", + "Note", + "OfflineConversionAlert", + "OfflineConversionError", + "OfflineConversionSummary", + "OfflineConversionUploadClientSummary", + "OfflineUserDataJob", + "OfflineUserDataJobMetadata", + "OperatingSystemVersionConstant", + "PaidOrganicSearchTermView", + "ParentalStatusView", + "PaymentsAccount", + "PerStoreView", + "PhoneCallDetails", + "ProductCategoryConstant", + "ProductGroupView", + "ProductLink", + "ProductLinkInvitation", + "QualifyingQuestion", + "Recommendation", + "RecommendationSubscription", + "RemarketingAction", + "RemarketingSetting", + "SearchTermView", + "SharedCriterion", + "SharedSet", + "ShoppingPerformanceView", + "SmartCampaignSearchTermView", + "SmartCampaignSetting", + "ThirdPartyAppAnalyticsLink", + "ThirdPartyAppAnalyticsLinkIdentifier", + "TopicConstant", + "TopicView", + "TravelActivityGroupView", + "TravelActivityPerformanceView", + "UserInterest", + "UserList", + "UserLocationView", + "Video", + "WebpageView", +) diff --git a/google/ads/googleads/v15/resources/services/__init__.py b/google/ads/googleads/v15/resources/services/__init__.py new file mode 100644 index 000000000..89a37dc92 --- /dev/null +++ b/google/ads/googleads/v15/resources/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/v15/resources/types/__init__.py b/google/ads/googleads/v15/resources/types/__init__.py new file mode 100644 index 000000000..89a37dc92 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/v15/resources/types/accessible_bidding_strategy.py b/google/ads/googleads/v15/resources/types/accessible_bidding_strategy.py new file mode 100644 index 000000000..40a5698fd --- /dev/null +++ b/google/ads/googleads/v15/resources/types/accessible_bidding_strategy.py @@ -0,0 +1,336 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import bidding_strategy_type +from google.ads.googleads.v15.enums.types import ( + target_impression_share_location, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/resources/types/account_budget.py b/google/ads/googleads/v15/resources/types/account_budget.py new file mode 100644 index 000000000..db73b8ec5 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/account_budget.py @@ -0,0 +1,453 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import account_budget_proposal_type +from google.ads.googleads.v15.enums.types import account_budget_status +from google.ads.googleads.v15.enums.types import ( + spending_limit_type as gage_spending_limit_type, +) +from google.ads.googleads.v15.enums.types import time_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/resources/types/account_budget_proposal.py b/google/ads/googleads/v15/resources/types/account_budget_proposal.py new file mode 100644 index 000000000..596b966c1 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/account_budget_proposal.py @@ -0,0 +1,284 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import account_budget_proposal_status +from google.ads.googleads.v15.enums.types import account_budget_proposal_type +from google.ads.googleads.v15.enums.types import spending_limit_type +from google.ads.googleads.v15.enums.types import time_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/resources/types/account_link.py b/google/ads/googleads/v15/resources/types/account_link.py new file mode 100644 index 000000000..764653adb --- /dev/null +++ b/google/ads/googleads/v15/resources/types/account_link.py @@ -0,0 +1,259 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import account_link_status +from google.ads.googleads.v15.enums.types import linked_account_type +from google.ads.googleads.v15.enums.types import mobile_app_vendor + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "AccountLink", + "ThirdPartyAppAnalyticsLinkIdentifier", + "DataPartnerLinkIdentifier", + "GoogleAdsLinkIdentifier", + "AdvertisingPartnerLinkIdentifier", + }, +) + + +class AccountLink(proto.Message): + r"""Represents the 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. 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.v15.enums.types.AccountLinkStatusEnum.AccountLinkStatus): + The status of the link. + type_ (google.ads.googleads.v15.enums.types.LinkedAccountTypeEnum.LinkedAccountType): + Output only. The type of the linked account. + third_party_app_analytics (google.ads.googleads.v15.resources.types.ThirdPartyAppAnalyticsLinkIdentifier): + Immutable. A third party app analytics link. + + This field is a member of `oneof`_ ``linked_account``. + data_partner (google.ads.googleads.v15.resources.types.DataPartnerLinkIdentifier): + Output only. Data partner link. + + This field is a member of `oneof`_ ``linked_account``. + google_ads (google.ads.googleads.v15.resources.types.GoogleAdsLinkIdentifier): + Output only. Google Ads link. + + This field is a member of `oneof`_ ``linked_account``. + advertising_partner (google.ads.googleads.v15.resources.types.AdvertisingPartnerLinkIdentifier): + Output only. Advertising Partner 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", + ) + ) + data_partner: "DataPartnerLinkIdentifier" = proto.Field( + proto.MESSAGE, + number=6, + oneof="linked_account", + message="DataPartnerLinkIdentifier", + ) + google_ads: "GoogleAdsLinkIdentifier" = proto.Field( + proto.MESSAGE, + number=7, + oneof="linked_account", + message="GoogleAdsLinkIdentifier", + ) + advertising_partner: "AdvertisingPartnerLinkIdentifier" = proto.Field( + proto.MESSAGE, + number=10, + oneof="linked_account", + message="AdvertisingPartnerLinkIdentifier", + ) + + +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.v15.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, + ) + ) + + +class DataPartnerLinkIdentifier(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 GoogleAdsLinkIdentifier(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=3, + optional=True, + ) + + +class AdvertisingPartnerLinkIdentifier(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 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/ad.py b/google/ads/googleads/v15/resources/types/ad.py new file mode 100644 index 000000000..dbfa3ae58 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad.py @@ -0,0 +1,477 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import ad_type_infos +from google.ads.googleads.v15.common.types import custom_parameter +from google.ads.googleads.v15.common.types import final_app_url +from google.ads.googleads.v15.common.types import url_collection +from google.ads.googleads.v15.enums.types import ad_type +from google.ads.googleads.v15.enums.types import device +from google.ads.googleads.v15.enums.types import system_managed_entity_source + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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.v15.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.v15.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, + ShoppingComparisonListingAd and VideoAd. + + This field is a member of `oneof`_ ``_name``. + system_managed_resource_source (google.ads.googleads.v15.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.v15.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.v15.common.types.ExpandedTextAdInfo): + Details pertaining to an expanded text ad. + + This field is a member of `oneof`_ ``ad_data``. + call_ad (google.ads.googleads.v15.common.types.CallAdInfo): + Details pertaining to a call ad. + + This field is a member of `oneof`_ ``ad_data``. + expanded_dynamic_search_ad (google.ads.googleads.v15.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.v15.common.types.HotelAdInfo): + Details pertaining to a hotel ad. + + This field is a member of `oneof`_ ``ad_data``. + shopping_smart_ad (google.ads.googleads.v15.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.v15.common.types.ShoppingProductAdInfo): + Details pertaining to a Shopping product ad. + + This field is a member of `oneof`_ ``ad_data``. + image_ad (google.ads.googleads.v15.common.types.ImageAdInfo): + Immutable. Details pertaining to an Image ad. + + This field is a member of `oneof`_ ``ad_data``. + video_ad (google.ads.googleads.v15.common.types.VideoAdInfo): + Details pertaining to a Video ad. + + This field is a member of `oneof`_ ``ad_data``. + video_responsive_ad (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.common.types.ResponsiveDisplayAdInfo): + Details pertaining to a responsive display + ad. + + This field is a member of `oneof`_ ``ad_data``. + local_ad (google.ads.googleads.v15.common.types.LocalAdInfo): + Details pertaining to a local ad. + + This field is a member of `oneof`_ ``ad_data``. + display_upload_ad (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.common.types.AppPreRegistrationAdInfo): + Details pertaining to an app pre-registration + ad. + + This field is a member of `oneof`_ ``ad_data``. + discovery_multi_asset_ad (google.ads.googleads.v15.common.types.DiscoveryMultiAssetAdInfo): + Details pertaining to a discovery multi asset + ad. + + This field is a member of `oneof`_ ``ad_data``. + discovery_carousel_ad (google.ads.googleads.v15.common.types.DiscoveryCarouselAdInfo): + Details pertaining to a discovery carousel + ad. + + This field is a member of `oneof`_ ``ad_data``. + discovery_video_responsive_ad (google.ads.googleads.v15.common.types.DiscoveryVideoResponsiveAdInfo): + Details pertaining to a discovery video + responsive ad. + + This field is a member of `oneof`_ ``ad_data``. + travel_ad (google.ads.googleads.v15.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, + ) + call_ad: ad_type_infos.CallAdInfo = proto.Field( + proto.MESSAGE, + number=49, + oneof="ad_data", + message=ad_type_infos.CallAdInfo, + ) + 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, + ) + ) + discovery_multi_asset_ad: ad_type_infos.DiscoveryMultiAssetAdInfo = ( + proto.Field( + proto.MESSAGE, + number=51, + oneof="ad_data", + message=ad_type_infos.DiscoveryMultiAssetAdInfo, + ) + ) + discovery_carousel_ad: ad_type_infos.DiscoveryCarouselAdInfo = proto.Field( + proto.MESSAGE, + number=52, + oneof="ad_data", + message=ad_type_infos.DiscoveryCarouselAdInfo, + ) + discovery_video_responsive_ad: ad_type_infos.DiscoveryVideoResponsiveAdInfo = proto.Field( + proto.MESSAGE, + number=60, + oneof="ad_data", + message=ad_type_infos.DiscoveryVideoResponsiveAdInfo, + ) + 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/v15/resources/types/ad_group.py b/google/ads/googleads/v15/resources/types/ad_group.py new file mode 100644 index 000000000..07625c2b6 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group.py @@ -0,0 +1,385 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import custom_parameter +from google.ads.googleads.v15.common.types import ( + targeting_setting as gagc_targeting_setting, +) +from google.ads.googleads.v15.enums.types import ad_group_ad_rotation_mode +from google.ads.googleads.v15.enums.types import ad_group_status +from google.ads.googleads.v15.enums.types import ad_group_type +from google.ads.googleads.v15.enums.types import asset_field_type +from google.ads.googleads.v15.enums.types import asset_set_type +from google.ads.googleads.v15.enums.types import bidding_source +from google.ads.googleads.v15.enums.types import targeting_dimension + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.AdGroupStatusEnum.AdGroupStatus): + The status of the ad group. + type_ (google.ads.googleads.v15.enums.types.AdGroupTypeEnum.AdGroupType): + Immutable. The type of the ad group. + ad_rotation_mode (google.ads.googleads.v15.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.v15.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 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) override. If the ad + group's campaign bidding strategy is TargetRoas or + MaximizeConversionValue (with its target_roas field set), + then this field overrides the target ROAS specified in the + campaign's bidding strategy. Otherwise, this value is + ignored. + + 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``. + optimized_targeting_enabled (bool): + True if optimized targeting is enabled. + Optimized Targeting is the replacement for + Audience Expansion. + display_custom_bid_dimension (google.ads.googleads.v15.enums.types.TargetingDimensionEnum.TargetingDimension): + Allows advertisers to 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.v15.common.types.TargetingSetting): + Setting for targeting related features. + audience_setting (google.ads.googleads.v15.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.v15.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.v15.enums.types.BiddingSourceEnum.BiddingSource): + Output only. Source of the effective target + ROAS. 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.v15.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.v15.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. + """ + + 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, + ) + + 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, + ) + optimized_targeting_enabled: bool = proto.Field( + proto.BOOL, + number=59, + ) + 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, + ) + 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/ad_group_ad.py b/google/ads/googleads/v15/resources/types/ad_group_ad.py new file mode 100644 index 000000000..e70d6f017 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_ad.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import policy +from google.ads.googleads.v15.enums.types import ad_group_ad_status +from google.ads.googleads.v15.enums.types import ad_strength as gage_ad_strength +from google.ads.googleads.v15.enums.types import policy_approval_status +from google.ads.googleads.v15.enums.types import policy_review_status +from google.ads.googleads.v15.resources.types import ad as gagr_ad + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "AdGroupAd", + "AdGroupAdPolicySummary", + }, +) + + +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.v15.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.v15.resources.types.Ad): + Immutable. The ad. + policy_summary (google.ads.googleads.v15.resources.types.AdGroupAdPolicySummary): + Output only. Policy information for the ad. + ad_strength (google.ads.googleads.v15.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. + """ + + 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, + ) + 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, + ) + + +class AdGroupAdPolicySummary(proto.Message): + r"""Contains policy information for an ad. + Attributes: + policy_topic_entries (MutableSequence[google.ads.googleads.v15.common.types.PolicyTopicEntry]): + Output only. The list of policy findings for + this ad. + review_status (google.ads.googleads.v15.enums.types.PolicyReviewStatusEnum.PolicyReviewStatus): + Output only. Where in the review process this + ad is. + approval_status (google.ads.googleads.v15.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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/ad_group_ad_asset_combination_view.py b/google/ads/googleads/v15/resources/types/ad_group_ad_asset_combination_view.py new file mode 100644 index 000000000..dbd252c9e --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_ad_asset_combination_view.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import asset_usage + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/ad_group_ad_asset_view.py b/google/ads/googleads/v15/resources/types/ad_group_ad_asset_view.py new file mode 100644 index 000000000..cb3636bc0 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_ad_asset_view.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import policy +from google.ads.googleads.v15.enums.types import asset_field_type +from google.ads.googleads.v15.enums.types import asset_performance_label +from google.ads.googleads.v15.enums.types import asset_source +from google.ads.googleads.v15.enums.types import policy_approval_status +from google.ads.googleads.v15.enums.types import policy_review_status +from google.ads.googleads.v15.enums.types import served_asset_field_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "AdGroupAdAssetView", + "AdGroupAdAssetPolicySummary", + }, +) + + +class AdGroupAdAssetView(proto.Message): + r"""A link between an AdGroupAd and an Asset. + Currently we only support AdGroupAdAssetView for AppAds and + Responsive Search 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.v15.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.v15.resources.types.AdGroupAdAssetPolicySummary): + Output only. Policy information for the ad + group ad asset. + performance_label (google.ads.googleads.v15.enums.types.AssetPerformanceLabelEnum.AssetPerformanceLabel): + Output only. Performance of an asset linkage. + pinned_field (google.ads.googleads.v15.enums.types.ServedAssetFieldTypeEnum.ServedAssetFieldType): + Output only. Pinned field. + source (google.ads.googleads.v15.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.v15.common.types.PolicyTopicEntry]): + Output only. The list of policy findings for + the ad group ad asset. + review_status (google.ads.googleads.v15.enums.types.PolicyReviewStatusEnum.PolicyReviewStatus): + Output only. Where in the review process this + ad group ad asset is. + approval_status (google.ads.googleads.v15.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/v15/resources/types/ad_group_ad_label.py b/google/ads/googleads/v15/resources/types/ad_group_ad_label.py new file mode 100644 index 000000000..7102f940f --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_ad_label.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/ad_group_asset.py b/google/ads/googleads/v15/resources/types/ad_group_asset.py new file mode 100644 index 000000000..549512b09 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_asset.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import asset_policy +from google.ads.googleads.v15.enums.types import asset_field_type +from google.ads.googleads.v15.enums.types import asset_link_primary_status +from google.ads.googleads.v15.enums.types import ( + asset_link_primary_status_reason, +) +from google.ads.googleads.v15.enums.types import asset_link_status +from google.ads.googleads.v15.enums.types import asset_source + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.AssetFieldTypeEnum.AssetFieldType): + Required. Immutable. Role that the asset + takes under the linked ad group. + source (google.ads.googleads.v15.enums.types.AssetSourceEnum.AssetSource): + Output only. Source of the adgroup asset + link. + status (google.ads.googleads.v15.enums.types.AssetLinkStatusEnum.AssetLinkStatus): + Status of the ad group asset. + primary_status (google.ads.googleads.v15.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.v15.common.types.AssetLinkPrimaryStatusDetails]): + Output only. Provides the details of the + primary status and its associated reasons. + primary_status_reasons (MutableSequence[google.ads.googleads.v15.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/v15/resources/types/ad_group_asset_set.py b/google/ads/googleads/v15/resources/types/ad_group_asset_set.py new file mode 100644 index 000000000..d56c305b9 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_asset_set.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import asset_set_link_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/ad_group_audience_view.py b/google/ads/googleads/v15/resources/types/ad_group_audience_view.py new file mode 100644 index 000000000..5d23c116b --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_audience_view.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/ad_group_bid_modifier.py b/google/ads/googleads/v15/resources/types/ad_group_bid_modifier.py new file mode 100644 index 000000000..85207bcdc --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_bid_modifier.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import criteria +from google.ads.googleads.v15.enums.types import ( + bid_modifier_source as gage_bid_modifier_source, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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. The range is 1.0 - 6.0 for + PreferredContent. 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.v15.enums.types.BidModifierSourceEnum.BidModifierSource): + Output only. Bid modifier source. + hotel_date_selection_type (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.common.types.DeviceInfo): + Immutable. A device criterion. + + This field is a member of `oneof`_ ``criterion``. + hotel_check_in_date_range (google.ads.googleads.v15.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/v15/resources/types/ad_group_criterion.py b/google/ads/googleads/v15/resources/types/ad_group_criterion.py new file mode 100644 index 000000000..49d0ddccd --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_criterion.py @@ -0,0 +1,701 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import criteria +from google.ads.googleads.v15.common.types import custom_parameter +from google.ads.googleads.v15.enums.types import ( + ad_group_criterion_approval_status, +) +from google.ads.googleads.v15.enums.types import ad_group_criterion_status +from google.ads.googleads.v15.enums.types import bidding_source +from google.ads.googleads.v15.enums.types import criterion_system_serving_status +from google.ads.googleads.v15.enums.types import criterion_type +from google.ads.googleads.v15.enums.types import quality_score_bucket + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "AdGroupCriterion", + }, +) + + +class AdGroupCriterion(proto.Message): + r"""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: + 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.v15.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.v15.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.v15.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.v15.enums.types.CriterionSystemServingStatusEnum.CriterionSystemServingStatus): + Output only. Serving status of the criterion. + approval_status (google.ads.googleads.v15.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.v15.enums.types.BiddingSourceEnum.BiddingSource): + Output only. Source of the effective CPC bid. + effective_cpm_bid_source (google.ads.googleads.v15.enums.types.BiddingSourceEnum.BiddingSource): + Output only. Source of the effective CPM bid. + effective_cpv_bid_source (google.ads.googleads.v15.enums.types.BiddingSourceEnum.BiddingSource): + Output only. Source of the effective CPV bid. + effective_percent_cpc_bid_source (google.ads.googleads.v15.enums.types.BiddingSourceEnum.BiddingSource): + Output only. Source of the effective Percent + CPC bid. + position_estimates (google.ads.googleads.v15.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.v15.common.types.CustomParameter]): + The list of mappings used to substitute custom parameter + tags in a ``tracking_url_template``, ``final_urls``, or + ``mobile_final_urls``. + keyword (google.ads.googleads.v15.common.types.KeywordInfo): + Immutable. Keyword. + + This field is a member of `oneof`_ ``criterion``. + placement (google.ads.googleads.v15.common.types.PlacementInfo): + Immutable. Placement. + + This field is a member of `oneof`_ ``criterion``. + mobile_app_category (google.ads.googleads.v15.common.types.MobileAppCategoryInfo): + Immutable. Mobile app category. + + This field is a member of `oneof`_ ``criterion``. + mobile_application (google.ads.googleads.v15.common.types.MobileApplicationInfo): + Immutable. Mobile application. + + This field is a member of `oneof`_ ``criterion``. + listing_group (google.ads.googleads.v15.common.types.ListingGroupInfo): + Immutable. Listing group. + + This field is a member of `oneof`_ ``criterion``. + age_range (google.ads.googleads.v15.common.types.AgeRangeInfo): + Immutable. Age range. + + This field is a member of `oneof`_ ``criterion``. + gender (google.ads.googleads.v15.common.types.GenderInfo): + Immutable. Gender. + + This field is a member of `oneof`_ ``criterion``. + income_range (google.ads.googleads.v15.common.types.IncomeRangeInfo): + Immutable. Income range. + + This field is a member of `oneof`_ ``criterion``. + parental_status (google.ads.googleads.v15.common.types.ParentalStatusInfo): + Immutable. Parental status. + + This field is a member of `oneof`_ ``criterion``. + user_list (google.ads.googleads.v15.common.types.UserListInfo): + Immutable. User List. + The Similar Audiences sunset starts May 2023. + Refer to + https://ads-developers.googleblog.com/2022/11/announcing-deprecation-and-sunset-of.html + for other options. + + This field is a member of `oneof`_ ``criterion``. + youtube_video (google.ads.googleads.v15.common.types.YouTubeVideoInfo): + Immutable. YouTube Video. + + This field is a member of `oneof`_ ``criterion``. + youtube_channel (google.ads.googleads.v15.common.types.YouTubeChannelInfo): + Immutable. YouTube Channel. + + This field is a member of `oneof`_ ``criterion``. + topic (google.ads.googleads.v15.common.types.TopicInfo): + Immutable. Topic. + + This field is a member of `oneof`_ ``criterion``. + user_interest (google.ads.googleads.v15.common.types.UserInterestInfo): + Immutable. User Interest. + + This field is a member of `oneof`_ ``criterion``. + webpage (google.ads.googleads.v15.common.types.WebpageInfo): + Immutable. Webpage + + This field is a member of `oneof`_ ``criterion``. + app_payment_model (google.ads.googleads.v15.common.types.AppPaymentModelInfo): + Immutable. App Payment Model. + + This field is a member of `oneof`_ ``criterion``. + custom_affinity (google.ads.googleads.v15.common.types.CustomAffinityInfo): + Immutable. Custom Affinity. + + This field is a member of `oneof`_ ``criterion``. + custom_intent (google.ads.googleads.v15.common.types.CustomIntentInfo): + Immutable. Custom Intent. + + This field is a member of `oneof`_ ``criterion``. + custom_audience (google.ads.googleads.v15.common.types.CustomAudienceInfo): + Immutable. Custom Audience. + + This field is a member of `oneof`_ ``criterion``. + combined_audience (google.ads.googleads.v15.common.types.CombinedAudienceInfo): + Immutable. Combined Audience. + + This field is a member of `oneof`_ ``criterion``. + audience (google.ads.googleads.v15.common.types.AudienceInfo): + Immutable. Audience. + + This field is a member of `oneof`_ ``criterion``. + location (google.ads.googleads.v15.common.types.LocationInfo): + Immutable. Location. + + This field is a member of `oneof`_ ``criterion``. + language (google.ads.googleads.v15.common.types.LanguageInfo): + Immutable. Language. + + 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.v15.enums.types.QualityScoreBucketEnum.QualityScoreBucket): + Output only. The performance of the ad + compared to other advertisers. + post_click_quality_score (google.ads.googleads.v15.enums.types.QualityScoreBucketEnum.QualityScoreBucket): + Output only. The quality score of the landing + page. + search_predicted_ctr (google.ads.googleads.v15.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, + ) + 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/ad_group_criterion_customizer.py b/google/ads/googleads/v15/resources/types/ad_group_criterion_customizer.py new file mode 100644 index 000000000..ddd6be2b5 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_criterion_customizer.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import customizer_value +from google.ads.googleads.v15.enums.types import customizer_value_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.CustomizerValueStatusEnum.CustomizerValueStatus): + Output only. The status of the ad group + criterion customizer. + value (google.ads.googleads.v15.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/v15/resources/types/ad_group_criterion_label.py b/google/ads/googleads/v15/resources/types/ad_group_criterion_label.py new file mode 100644 index 000000000..00e4e5045 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_criterion_label.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/ad_group_criterion_simulation.py b/google/ads/googleads/v15/resources/types/ad_group_criterion_simulation.py new file mode 100644 index 000000000..053eaab80 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_criterion_simulation.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import simulation +from google.ads.googleads.v15.enums.types import simulation_modification_method +from google.ads.googleads.v15.enums.types import simulation_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.SimulationTypeEnum.SimulationType): + Output only. The field that the simulation + modifies. + modification_method (google.ads.googleads.v15.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.v15.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.v15.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/v15/resources/types/ad_group_customizer.py b/google/ads/googleads/v15/resources/types/ad_group_customizer.py new file mode 100644 index 000000000..0fd75de8a --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_customizer.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import customizer_value +from google.ads.googleads.v15.enums.types import customizer_value_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.CustomizerValueStatusEnum.CustomizerValueStatus): + Output only. The status of the ad group + customizer. + value (google.ads.googleads.v15.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/v15/resources/types/ad_group_extension_setting.py b/google/ads/googleads/v15/resources/types/ad_group_extension_setting.py new file mode 100644 index 000000000..965a1ed74 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_extension_setting.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import extension_setting_device +from google.ads.googleads.v15.enums.types import ( + extension_type as gage_extension_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "AdGroupExtensionSetting", + }, +) + + +class AdGroupExtensionSetting(proto.Message): + r"""An ad group extension setting. + .. _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 extension + setting. AdGroupExtensionSetting resource names have the + form: + + ``customers/{customer_id}/adGroupExtensionSettings/{ad_group_id}~{extension_type}`` + extension_type (google.ads.googleads.v15.enums.types.ExtensionTypeEnum.ExtensionType): + Immutable. The extension type of the ad group + extension setting. + ad_group (str): + Immutable. The resource name of the ad group. The linked + extension feed items will serve under this ad group. AdGroup + resource names have the form: + + ``customers/{customer_id}/adGroups/{ad_group_id}`` + + This field is a member of `oneof`_ ``_ad_group``. + extension_feed_items (MutableSequence[str]): + The resource names of the extension feed items to serve + under the ad group. ExtensionFeedItem resource names have + the form: + + ``customers/{customer_id}/extensionFeedItems/{feed_item_id}`` + device (google.ads.googleads.v15.enums.types.ExtensionSettingDeviceEnum.ExtensionSettingDevice): + The device for which the extensions will + serve. Optional. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + extension_type: gage_extension_type.ExtensionTypeEnum.ExtensionType = ( + proto.Field( + proto.ENUM, + number=2, + enum=gage_extension_type.ExtensionTypeEnum.ExtensionType, + ) + ) + ad_group: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + extension_feed_items: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=7, + ) + device: extension_setting_device.ExtensionSettingDeviceEnum.ExtensionSettingDevice = proto.Field( + proto.ENUM, + number=5, + enum=extension_setting_device.ExtensionSettingDeviceEnum.ExtensionSettingDevice, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/ad_group_feed.py b/google/ads/googleads/v15/resources/types/ad_group_feed.py new file mode 100644 index 000000000..c01266115 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_feed.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import ( + matching_function as gagc_matching_function, +) +from google.ads.googleads.v15.enums.types import feed_link_status +from google.ads.googleads.v15.enums.types import placeholder_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "AdGroupFeed", + }, +) + + +class AdGroupFeed(proto.Message): + r"""An ad group feed. + .. _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 feed. Ad group + feed resource names have the form: + + \`customers/{customer_id}/adGroupFeeds/{ad_group_id}~{feed_id} + feed (str): + Immutable. The feed being linked to the ad + group. + + This field is a member of `oneof`_ ``_feed``. + ad_group (str): + Immutable. The ad group being linked to the + feed. + + This field is a member of `oneof`_ ``_ad_group``. + placeholder_types (MutableSequence[google.ads.googleads.v15.enums.types.PlaceholderTypeEnum.PlaceholderType]): + Indicates which placeholder types the feed + may populate under the connected ad group. + Required. + matching_function (google.ads.googleads.v15.common.types.MatchingFunction): + Matching function associated with the + AdGroupFeed. The matching function is used to + filter the set of feed items selected. Required. + status (google.ads.googleads.v15.enums.types.FeedLinkStatusEnum.FeedLinkStatus): + Output only. Status of the ad group feed. + This field is read-only. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + feed: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + ad_group: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + placeholder_types: MutableSequence[ + placeholder_type.PlaceholderTypeEnum.PlaceholderType + ] = proto.RepeatedField( + proto.ENUM, + number=4, + enum=placeholder_type.PlaceholderTypeEnum.PlaceholderType, + ) + matching_function: gagc_matching_function.MatchingFunction = proto.Field( + proto.MESSAGE, + number=5, + message=gagc_matching_function.MatchingFunction, + ) + status: feed_link_status.FeedLinkStatusEnum.FeedLinkStatus = proto.Field( + proto.ENUM, + number=6, + enum=feed_link_status.FeedLinkStatusEnum.FeedLinkStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/ad_group_label.py b/google/ads/googleads/v15/resources/types/ad_group_label.py new file mode 100644 index 000000000..d2c73fb21 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_label.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/ad_group_simulation.py b/google/ads/googleads/v15/resources/types/ad_group_simulation.py new file mode 100644 index 000000000..c12d372da --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_group_simulation.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import simulation +from google.ads.googleads.v15.enums.types import simulation_modification_method +from google.ads.googleads.v15.enums.types import simulation_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.SimulationTypeEnum.SimulationType): + Output only. The field that the simulation + modifies. + modification_method (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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/v15/resources/types/ad_parameter.py b/google/ads/googleads/v15/resources/types/ad_parameter.py new file mode 100644 index 000000000..1f936dbb9 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_parameter.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/ad_schedule_view.py b/google/ads/googleads/v15/resources/types/ad_schedule_view.py new file mode 100644 index 000000000..9ab64b12f --- /dev/null +++ b/google/ads/googleads/v15/resources/types/ad_schedule_view.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/age_range_view.py b/google/ads/googleads/v15/resources/types/age_range_view.py new file mode 100644 index 000000000..524f066e5 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/age_range_view.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/android_privacy_shared_key_google_ad_group.py b/google/ads/googleads/v15/resources/types/android_privacy_shared_key_google_ad_group.py new file mode 100644 index 000000000..700238532 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/android_privacy_shared_key_google_ad_group.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + android_privacy_interaction_type as gage_android_privacy_interaction_type, +) +from google.ads.googleads.v15.enums.types import ( + android_privacy_network_type as gage_android_privacy_network_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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/v15/resources/types/android_privacy_shared_key_google_campaign.py b/google/ads/googleads/v15/resources/types/android_privacy_shared_key_google_campaign.py new file mode 100644 index 000000000..9eadb324b --- /dev/null +++ b/google/ads/googleads/v15/resources/types/android_privacy_shared_key_google_campaign.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + android_privacy_interaction_type as gage_android_privacy_interaction_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/android_privacy_shared_key_google_network_type.py b/google/ads/googleads/v15/resources/types/android_privacy_shared_key_google_network_type.py new file mode 100644 index 000000000..95f000290 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/android_privacy_shared_key_google_network_type.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + android_privacy_interaction_type as gage_android_privacy_interaction_type, +) +from google.ads.googleads.v15.enums.types import ( + android_privacy_network_type as gage_android_privacy_network_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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/v15/resources/types/asset.py b/google/ads/googleads/v15/resources/types/asset.py new file mode 100644 index 000000000..ec7fd6954 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/asset.py @@ -0,0 +1,516 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import asset_types +from google.ads.googleads.v15.common.types import custom_parameter +from google.ads.googleads.v15.common.types import policy +from google.ads.googleads.v15.enums.types import ( + asset_field_type as gage_asset_field_type, +) +from google.ads.googleads.v15.enums.types import ( + asset_source as gage_asset_source, +) +from google.ads.googleads.v15.enums.types import asset_type +from google.ads.googleads.v15.enums.types import policy_approval_status +from google.ads.googleads.v15.enums.types import policy_review_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.enums.types.AssetSourceEnum.AssetSource): + Output only. Source of the asset. + policy_summary (google.ads.googleads.v15.resources.types.AssetPolicySummary): + Output only. Policy information for the + asset. + field_type_policy_summaries (MutableSequence[google.ads.googleads.v15.resources.types.AssetFieldTypePolicySummary]): + Output only. Policy information for the asset + for each FieldType. + youtube_video_asset (google.ads.googleads.v15.common.types.YoutubeVideoAsset): + Immutable. A YouTube video asset. + + This field is a member of `oneof`_ ``asset_data``. + media_bundle_asset (google.ads.googleads.v15.common.types.MediaBundleAsset): + Immutable. A media bundle asset. + + This field is a member of `oneof`_ ``asset_data``. + image_asset (google.ads.googleads.v15.common.types.ImageAsset): + Output only. An image asset. + + This field is a member of `oneof`_ ``asset_data``. + text_asset (google.ads.googleads.v15.common.types.TextAsset): + Immutable. A text asset. + + This field is a member of `oneof`_ ``asset_data``. + lead_form_asset (google.ads.googleads.v15.common.types.LeadFormAsset): + A lead form asset. + + This field is a member of `oneof`_ ``asset_data``. + book_on_google_asset (google.ads.googleads.v15.common.types.BookOnGoogleAsset): + A book on google asset. + + This field is a member of `oneof`_ ``asset_data``. + promotion_asset (google.ads.googleads.v15.common.types.PromotionAsset): + A promotion asset. + + This field is a member of `oneof`_ ``asset_data``. + callout_asset (google.ads.googleads.v15.common.types.CalloutAsset): + A callout asset. + + This field is a member of `oneof`_ ``asset_data``. + structured_snippet_asset (google.ads.googleads.v15.common.types.StructuredSnippetAsset): + A structured snippet asset. + + This field is a member of `oneof`_ ``asset_data``. + sitelink_asset (google.ads.googleads.v15.common.types.SitelinkAsset): + A sitelink asset. + + This field is a member of `oneof`_ ``asset_data``. + page_feed_asset (google.ads.googleads.v15.common.types.PageFeedAsset): + A page feed asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_education_asset (google.ads.googleads.v15.common.types.DynamicEducationAsset): + A dynamic education asset. + + This field is a member of `oneof`_ ``asset_data``. + mobile_app_asset (google.ads.googleads.v15.common.types.MobileAppAsset): + A mobile app asset. + + This field is a member of `oneof`_ ``asset_data``. + hotel_callout_asset (google.ads.googleads.v15.common.types.HotelCalloutAsset): + A hotel callout asset. + + This field is a member of `oneof`_ ``asset_data``. + call_asset (google.ads.googleads.v15.common.types.CallAsset): + A call asset. + + This field is a member of `oneof`_ ``asset_data``. + price_asset (google.ads.googleads.v15.common.types.PriceAsset): + A price asset. + + This field is a member of `oneof`_ ``asset_data``. + call_to_action_asset (google.ads.googleads.v15.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.v15.common.types.DynamicRealEstateAsset): + A dynamic real estate asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_custom_asset (google.ads.googleads.v15.common.types.DynamicCustomAsset): + A dynamic custom asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_hotels_and_rentals_asset (google.ads.googleads.v15.common.types.DynamicHotelsAndRentalsAsset): + A dynamic hotels and rentals asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_flights_asset (google.ads.googleads.v15.common.types.DynamicFlightsAsset): + A dynamic flights asset. + + This field is a member of `oneof`_ ``asset_data``. + discovery_carousel_card_asset (google.ads.googleads.v15.common.types.DiscoveryCarouselCardAsset): + Immutable. A discovery carousel card asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_travel_asset (google.ads.googleads.v15.common.types.DynamicTravelAsset): + A dynamic travel asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_local_asset (google.ads.googleads.v15.common.types.DynamicLocalAsset): + A dynamic local asset. + + This field is a member of `oneof`_ ``asset_data``. + dynamic_jobs_asset (google.ads.googleads.v15.common.types.DynamicJobsAsset): + A dynamic jobs asset. + + This field is a member of `oneof`_ ``asset_data``. + location_asset (google.ads.googleads.v15.common.types.LocationAsset): + Output only. A location asset. + + This field is a member of `oneof`_ ``asset_data``. + hotel_property_asset (google.ads.googleads.v15.common.types.HotelPropertyAsset): + Immutable. A hotel property 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", + ) + 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, + ) + discovery_carousel_card_asset: asset_types.DiscoveryCarouselCardAsset = ( + proto.Field( + proto.MESSAGE, + number=34, + oneof="asset_data", + message=asset_types.DiscoveryCarouselCardAsset, + ) + ) + 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, + ) + + +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.v15.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.v15.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.v15.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.v15.common.types.PolicyTopicEntry]): + Output only. The list of policy findings for + this asset. + review_status (google.ads.googleads.v15.enums.types.PolicyReviewStatusEnum.PolicyReviewStatus): + Output only. Where in the review process this + asset is. + approval_status (google.ads.googleads.v15.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/v15/resources/types/asset_field_type_view.py b/google/ads/googleads/v15/resources/types/asset_field_type_view.py new file mode 100644 index 000000000..2f49886a7 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/asset_field_type_view.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import asset_field_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/asset_group.py b/google/ads/googleads/v15/resources/types/asset_group.py new file mode 100644 index 000000000..e63c04c64 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/asset_group.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ad_strength as gage_ad_strength +from google.ads.googleads.v15.enums.types import asset_group_primary_status +from google.ads.googleads.v15.enums.types import ( + asset_group_primary_status_reason, +) +from google.ads.googleads.v15.enums.types import asset_group_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "AssetGroup", + }, +) + + +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.v15.enums.types.AssetGroupStatusEnum.AssetGroupStatus): + The status of the asset group. + primary_status (google.ads.googleads.v15.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.v15.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.v15.enums.types.AdStrengthEnum.AdStrength): + Output only. Overall ad strength 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/asset_group_asset.py b/google/ads/googleads/v15/resources/types/asset_group_asset.py new file mode 100644 index 000000000..595fdec10 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/asset_group_asset.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import asset_policy +from google.ads.googleads.v15.common.types import ( + policy_summary as gagc_policy_summary, +) +from google.ads.googleads.v15.enums.types import asset_field_type +from google.ads.googleads.v15.enums.types import asset_link_primary_status +from google.ads.googleads.v15.enums.types import ( + asset_link_primary_status_reason, +) +from google.ads.googleads.v15.enums.types import asset_link_status +from google.ads.googleads.v15.enums.types import asset_performance_label +from google.ads.googleads.v15.enums.types import asset_source + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.enums.types.AssetLinkStatusEnum.AssetLinkStatus): + The status of the link between an asset and + asset group. + primary_status (google.ads.googleads.v15.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.v15.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.v15.common.types.AssetLinkPrimaryStatusDetails]): + Output only. Provides the details of the + primary status and its associated reasons. + performance_label (google.ads.googleads.v15.enums.types.AssetPerformanceLabelEnum.AssetPerformanceLabel): + Output only. The performance of this asset + group asset. + policy_summary (google.ads.googleads.v15.common.types.PolicySummary): + Output only. The policy information for this + asset group asset. + source (google.ads.googleads.v15.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, + ) + performance_label: asset_performance_label.AssetPerformanceLabelEnum.AssetPerformanceLabel = proto.Field( + proto.ENUM, + number=6, + enum=asset_performance_label.AssetPerformanceLabelEnum.AssetPerformanceLabel, + ) + 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/v15/resources/types/asset_group_listing_group_filter.py b/google/ads/googleads/v15/resources/types/asset_group_listing_group_filter.py new file mode 100644 index 000000000..3c559bf1a --- /dev/null +++ b/google/ads/googleads/v15/resources/types/asset_group_listing_group_filter.py @@ -0,0 +1,452 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + listing_group_filter_custom_attribute_index, +) +from google.ads.googleads.v15.enums.types import ( + listing_group_filter_listing_source, +) +from google.ads.googleads.v15.enums.types import ( + listing_group_filter_product_category_level, +) +from google.ads.googleads.v15.enums.types import ( + listing_group_filter_product_channel, +) +from google.ads.googleads.v15.enums.types import ( + listing_group_filter_product_condition, +) +from google.ads.googleads.v15.enums.types import ( + listing_group_filter_product_type_level, +) +from google.ads.googleads.v15.enums.types import listing_group_filter_type_enum + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.ListingGroupFilterTypeEnum.ListingGroupFilterType): + Immutable. Type of a listing group filter + node. + listing_source (google.ads.googleads.v15.enums.types.ListingGroupFilterListingSourceEnum.ListingGroupFilterListingSource): + Immutable. The source of listings filtered by + this listing group filter. + case_value (google.ads.googleads.v15.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.v15.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.v15.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.v15.resources.types.ListingGroupFilterDimension.ProductCategory): + Category of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_brand (google.ads.googleads.v15.resources.types.ListingGroupFilterDimension.ProductBrand): + Brand of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_channel (google.ads.googleads.v15.resources.types.ListingGroupFilterDimension.ProductChannel): + Locality of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_condition (google.ads.googleads.v15.resources.types.ListingGroupFilterDimension.ProductCondition): + Condition of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_custom_attribute (google.ads.googleads.v15.resources.types.ListingGroupFilterDimension.ProductCustomAttribute): + Custom attribute of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_item_id (google.ads.googleads.v15.resources.types.ListingGroupFilterDimension.ProductItemId): + Item id of a product offer. + + This field is a member of `oneof`_ ``dimension``. + product_type (google.ads.googleads.v15.resources.types.ListingGroupFilterDimension.ProductType): + Type of a product offer. + + This field is a member of `oneof`_ ``dimension``. + webpage (google.ads.googleads.v15.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``. + """ + + 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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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", + ) + + 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/asset_group_product_group_view.py b/google/ads/googleads/v15/resources/types/asset_group_product_group_view.py new file mode 100644 index 000000000..019c3369d --- /dev/null +++ b/google/ads/googleads/v15/resources/types/asset_group_product_group_view.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/asset_group_signal.py b/google/ads/googleads/v15/resources/types/asset_group_signal.py new file mode 100644 index 000000000..ed2d70c7d --- /dev/null +++ b/google/ads/googleads/v15/resources/types/asset_group_signal.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import criteria +from google.ads.googleads.v15.enums.types import ( + asset_group_signal_approval_status, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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/v15/resources/types/asset_group_top_combination_view.py b/google/ads/googleads/v15/resources/types/asset_group_top_combination_view.py new file mode 100644 index 000000000..8224c5da0 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/asset_group_top_combination_view.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import asset_usage + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "AssetGroupTopCombinationView", + "AssetGroupAssetCombinationData", + }, +) + + +class AssetGroupTopCombinationView(proto.Message): + r"""A view on the usage of ad group ad asset combination. + 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.v15.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.v15.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/v15/resources/types/asset_set.py b/google/ads/googleads/v15/resources/types/asset_set.py new file mode 100644 index 000000000..22f463f7d --- /dev/null +++ b/google/ads/googleads/v15/resources/types/asset_set.py @@ -0,0 +1,208 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import asset_set_types +from google.ads.googleads.v15.enums.types import asset_set_status +from google.ads.googleads.v15.enums.types import asset_set_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.AssetSetTypeEnum.AssetSetType): + Required. Immutable. The type of the asset + set. Required. + status (google.ads.googleads.v15.enums.types.AssetSetStatusEnum.AssetSetStatus): + Output only. The status of the asset set. + Read-only. + merchant_center_feed (google.ads.googleads.v15.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 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.v15.resources.types.AssetSet.HotelPropertyData): + Output only. For Performance Max for travel + goals campaigns with a Hotel Center account + link. Read-only. + location_set (google.ads.googleads.v15.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.v15.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.v15.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, + ) + + 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, + ) + 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/v15/resources/types/asset_set_asset.py b/google/ads/googleads/v15/resources/types/asset_set_asset.py new file mode 100644 index 000000000..3c9a8c026 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/asset_set_asset.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import asset_set_asset_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/asset_set_type_view.py b/google/ads/googleads/v15/resources/types/asset_set_type_view.py new file mode 100644 index 000000000..636d6d5c4 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/asset_set_type_view.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + asset_set_type as gage_asset_set_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/audience.py b/google/ads/googleads/v15/resources/types/audience.py new file mode 100644 index 000000000..89f914c79 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/audience.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import audiences +from google.ads.googleads.v15.enums.types import audience_scope +from google.ads.googleads.v15.enums.types import audience_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.common.types.AudienceDimension]): + Positive dimensions specifying the audience + composition. + exclusion_dimension (google.ads.googleads.v15.common.types.AudienceExclusionDimension): + Negative dimension specifying the audience + composition. + scope (google.ads.googleads.v15.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/v15/resources/types/batch_job.py b/google/ads/googleads/v15/resources/types/batch_job.py new file mode 100644 index 000000000..38e47b32b --- /dev/null +++ b/google/ads/googleads/v15/resources/types/batch_job.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import batch_job_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.resources.types.BatchJob.BatchJobMetadata): + Output only. Contains additional information + about this batch job. + status (google.ads.googleads.v15.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/v15/resources/types/bidding_data_exclusion.py b/google/ads/googleads/v15/resources/types/bidding_data_exclusion.py new file mode 100644 index 000000000..3c625065d --- /dev/null +++ b/google/ads/googleads/v15/resources/types/bidding_data_exclusion.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import advertising_channel_type +from google.ads.googleads.v15.enums.types import device +from google.ads.googleads.v15.enums.types import seasonality_event_scope +from google.ads.googleads.v15.enums.types import seasonality_event_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "BiddingDataExclusion", + }, +) + + +class BiddingDataExclusion(proto.Message): + r"""Represents a bidding data exclusion. + + See "About data exclusions" at + https://support.google.com/google-ads/answer/10370710. + + 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.v15.enums.types.SeasonalityEventScopeEnum.SeasonalityEventScope): + The scope of the data exclusion. + status (google.ads.googleads.v15.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.v15.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.v15.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/v15/resources/types/bidding_seasonality_adjustment.py b/google/ads/googleads/v15/resources/types/bidding_seasonality_adjustment.py new file mode 100644 index 000000000..5bdee4589 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/bidding_seasonality_adjustment.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import advertising_channel_type +from google.ads.googleads.v15.enums.types import device +from google.ads.googleads.v15.enums.types import seasonality_event_scope +from google.ads.googleads.v15.enums.types import seasonality_event_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "BiddingSeasonalityAdjustment", + }, +) + + +class BiddingSeasonalityAdjustment(proto.Message): + r"""Represents a bidding seasonality adjustment. + + 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.v15.enums.types.SeasonalityEventScopeEnum.SeasonalityEventScope): + The scope of the seasonality adjustment. + status (google.ads.googleads.v15.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.v15.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.v15.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/v15/resources/types/bidding_strategy.py b/google/ads/googleads/v15/resources/types/bidding_strategy.py new file mode 100644 index 000000000..7a757fa0c --- /dev/null +++ b/google/ads/googleads/v15/resources/types/bidding_strategy.py @@ -0,0 +1,255 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import bidding +from google.ads.googleads.v15.enums.types import bidding_strategy_status +from google.ads.googleads.v15.enums.types import bidding_strategy_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.BiddingStrategyStatusEnum.BiddingStrategyStatus): + Output only. The status of the bidding + strategy. + This field is read-only. + type_ (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/resources/types/bidding_strategy_simulation.py b/google/ads/googleads/v15/resources/types/bidding_strategy_simulation.py new file mode 100644 index 000000000..751bd3803 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/bidding_strategy_simulation.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import simulation +from google.ads.googleads.v15.enums.types import simulation_modification_method +from google.ads.googleads.v15.enums.types import simulation_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.SimulationTypeEnum.SimulationType): + Output only. The field that the simulation + modifies. + modification_method (google.ads.googleads.v15.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.v15.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.v15.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/v15/resources/types/billing_setup.py b/google/ads/googleads/v15/resources/types/billing_setup.py new file mode 100644 index 000000000..92f6e0387 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/billing_setup.py @@ -0,0 +1,223 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import billing_setup_status +from google.ads.googleads.v15.enums.types import time_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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.v15.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/v15/resources/types/call_view.py b/google/ads/googleads/v15/resources/types/call_view.py new file mode 100644 index 000000000..1fd11198a --- /dev/null +++ b/google/ads/googleads/v15/resources/types/call_view.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + call_tracking_display_location as gage_call_tracking_display_location, +) +from google.ads.googleads.v15.enums.types import call_type +from google.ads.googleads.v15.enums.types import google_voice_call_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.CallTrackingDisplayLocationEnum.CallTrackingDisplayLocation): + Output only. The call tracking display + location. + type_ (google.ads.googleads.v15.enums.types.CallTypeEnum.CallType): + Output only. The type of the call. + call_status (google.ads.googleads.v15.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/v15/resources/types/campaign.py b/google/ads/googleads/v15/resources/types/campaign.py new file mode 100644 index 000000000..1975d8151 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign.py @@ -0,0 +1,1320 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import bidding +from google.ads.googleads.v15.common.types import custom_parameter +from google.ads.googleads.v15.common.types import frequency_cap +from google.ads.googleads.v15.common.types import ( + real_time_bidding_setting as gagc_real_time_bidding_setting, +) +from google.ads.googleads.v15.common.types import ( + targeting_setting as gagc_targeting_setting, +) +from google.ads.googleads.v15.enums.types import ( + ad_serving_optimization_status as gage_ad_serving_optimization_status, +) +from google.ads.googleads.v15.enums.types import ( + advertising_channel_sub_type as gage_advertising_channel_sub_type, +) +from google.ads.googleads.v15.enums.types import ( + advertising_channel_type as gage_advertising_channel_type, +) +from google.ads.googleads.v15.enums.types import app_campaign_app_store +from google.ads.googleads.v15.enums.types import ( + app_campaign_bidding_strategy_goal_type, +) +from google.ads.googleads.v15.enums.types import ( + asset_automation_status as gage_asset_automation_status, +) +from google.ads.googleads.v15.enums.types import ( + asset_automation_type as gage_asset_automation_type, +) +from google.ads.googleads.v15.enums.types import asset_field_type +from google.ads.googleads.v15.enums.types import asset_set_type +from google.ads.googleads.v15.enums.types import ( + bidding_strategy_system_status as gage_bidding_strategy_system_status, +) +from google.ads.googleads.v15.enums.types import ( + bidding_strategy_type as gage_bidding_strategy_type, +) +from google.ads.googleads.v15.enums.types import brand_safety_suitability +from google.ads.googleads.v15.enums.types import campaign_experiment_type +from google.ads.googleads.v15.enums.types import campaign_primary_status +from google.ads.googleads.v15.enums.types import campaign_primary_status_reason +from google.ads.googleads.v15.enums.types import campaign_serving_status +from google.ads.googleads.v15.enums.types import campaign_status +from google.ads.googleads.v15.enums.types import ( + listing_type as gage_listing_type, +) +from google.ads.googleads.v15.enums.types import ( + location_source_type as gage_location_source_type, +) +from google.ads.googleads.v15.enums.types import ( + negative_geo_target_type as gage_negative_geo_target_type, +) +from google.ads.googleads.v15.enums.types import optimization_goal_type +from google.ads.googleads.v15.enums.types import ( + payment_mode as gage_payment_mode, +) +from google.ads.googleads.v15.enums.types import performance_max_upgrade_status +from google.ads.googleads.v15.enums.types import ( + positive_geo_target_type as gage_positive_geo_target_type, +) +from google.ads.googleads.v15.enums.types import ( + vanity_pharma_display_url_mode as gage_vanity_pharma_display_url_mode, +) +from google.ads.googleads.v15.enums.types import ( + vanity_pharma_text as gage_vanity_pharma_text, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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.v15.enums.types.CampaignServingStatusEnum.CampaignServingStatus): + Output only. The ad serving status of the + campaign. + bidding_strategy_system_status (google.ads.googleads.v15.enums.types.BiddingStrategySystemStatusEnum.BiddingStrategySystemStatus): + Output only. The system status of the + campaign's bidding strategy. + ad_serving_optimization_status (google.ads.googleads.v15.enums.types.AdServingOptimizationStatusEnum.AdServingOptimizationStatus): + The ad serving optimization status of the + campaign. + advertising_channel_type (google.ads.googleads.v15.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.v15.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.v15.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.v15.resources.types.Campaign.LocalServicesCampaignSettings): + The Local Services Campaign related settings. + travel_campaign_settings (google.ads.googleads.v15.resources.types.Campaign.TravelCampaignSettings): + Settings for Travel campaign. + discovery_campaign_settings (google.ads.googleads.v15.resources.types.Campaign.DiscoveryCampaignSettings): + Settings for Discovery campaign. + real_time_bidding_setting (google.ads.googleads.v15.common.types.RealTimeBiddingSetting): + Settings for Real-Time Bidding, a feature + only available for campaigns targeting the Ad + Exchange network. + network_settings (google.ads.googleads.v15.resources.types.Campaign.NetworkSettings): + The network settings for the campaign. + hotel_setting (google.ads.googleads.v15.resources.types.Campaign.HotelSettingInfo): + Immutable. The hotel setting for the + campaign. + dynamic_search_ads_setting (google.ads.googleads.v15.resources.types.Campaign.DynamicSearchAdsSetting): + The setting for controlling Dynamic Search + Ads (DSA). + shopping_setting (google.ads.googleads.v15.resources.types.Campaign.ShoppingSetting): + The setting for controlling Shopping + campaigns. + targeting_setting (google.ads.googleads.v15.common.types.TargetingSetting): + Setting for targeting related features. + audience_setting (google.ads.googleads.v15.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.v15.resources.types.Campaign.GeoTargetTypeSetting): + The setting for ads geotargeting. + local_campaign_setting (google.ads.googleads.v15.resources.types.Campaign.LocalCampaignSetting): + The setting for local campaign. + app_campaign_setting (google.ads.googleads.v15.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.v15.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 budget of the campaign. + + This field is a member of `oneof`_ ``_campaign_budget``. + bidding_strategy_type (google.ads.googleads.v15.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. + start_date (str): + The date when campaign started in serving + customer's timezone in YYYY-MM-DD format. + + This field is a member of `oneof`_ ``_start_date``. + campaign_group (str): + The campaign group this campaign belongs to. + + This field is a member of `oneof`_ ``_campaign_group``. + end_date (str): + The last day of the campaign in serving + customer's timezone in YYYY-MM-DD format. On + create, defaults to 2037-12-30, which means the + campaign will run indefinitely. To set an + existing campaign to run indefinitely, set this + field to 2037-12-30. + + This field is a member of `oneof`_ ``_end_date``. + 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.v15.common.types.FrequencyCapEntry]): + A list that limits how often each user will + see this campaign's ads. + video_brand_safety_suitability (google.ads.googleads.v15.enums.types.BrandSafetySuitabilityEnum.BrandSafetySuitability): + Output only. 3-Tier Brand Safety setting for + the campaign. + vanity_pharma (google.ads.googleads.v15.resources.types.Campaign.VanityPharma): + Describes how unbranded pharma ads will be + displayed. + selective_optimization (google.ads.googleads.v15.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.v15.resources.types.Campaign.OptimizationGoalSetting): + Optimization goal setting for this campaign, + which includes a set of optimization goal types. + tracking_setting (google.ads.googleads.v15.resources.types.Campaign.TrackingSetting): + Output only. Campaign-level settings for + tracking information. + payment_mode (google.ads.googleads.v15.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.v15.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.v15.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. + url_expansion_opt_out (bool): + Represents opting out of URL expansion to + more targeted URLs. If opted out (true), only + the final URLs in the asset group or URLs + specified in the advertiser's Google Merchant + Center or business data feeds are targeted. If + opted in (false), the entire domain will be + targeted. This field can only be set for + Performance Max campaigns, where the default + value is false. + + This field is a member of `oneof`_ ``_url_expansion_opt_out``. + performance_max_upgrade (google.ads.googleads.v15.resources.types.Campaign.PerformanceMaxUpgrade): + Output only. Information about campaigns + being upgraded to Performance Max. + hotel_property_asset_set (str): + Immutable. The 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.v15.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.v15.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. + bidding_strategy (str): + Portfolio bidding strategy used by campaign. + + This field is a member of `oneof`_ ``campaign_bidding_strategy``. + commission (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.common.types.TargetCpm): + A bidding strategy that automatically + optimizes cost per thousand impressions. + + 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. Indicates which Performance Max + campaign the campaign is upgraded to. + pre_upgrade_campaign (str): + Output only. Indicates legacy campaign + upgraded to Performance Max. + status (google.ads.googleads.v15.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 partner sites in the Google + Search 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 Google + Partner Network. This is available only to some + select Google partner accounts. + + 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): + Immutable. The linked Hotel Center account. + + This field is a member of `oneof`_ ``_hotel_center_id``. + """ + + hotel_center_id: int = proto.Field( + proto.INT64, + number=2, + 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``. + feeds (MutableSequence[str]): + The list of page feeds associated with the + campaign. + """ + + 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, + ) + feeds: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=9, + ) + + 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): + Immutable. 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. Only one + of feed_label or sales_country can be set. If used instead + of sales_country, the feed_label field accepts country codes + in the same format for example: 'XX'. Otherwise can be any + string used for feed label in Google Merchant Center. + 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]): + Immutable. The ads account IDs of advertising + partners cooperating within the campaign. + """ + + 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, + ) + + 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.v15.enums.types.PositiveGeoTargetTypeEnum.PositiveGeoTargetType): + The setting used for positive geotargeting in + this particular campaign. + negative_geo_target_type (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.enums.types.VanityPharmaDisplayUrlModeEnum.VanityPharmaDisplayUrlMode): + The display mode for vanity pharma URLs. + vanity_pharma_text (google.ads.googleads.v15.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 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.v15.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.v15.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``. + """ + + category_id: str = proto.Field( + proto.STRING, + number=1, + optional=True, + ) + manual_cpa_bid_micros: int = proto.Field( + proto.INT64, + number=2, + 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 DiscoveryCampaignSettings(proto.Message): + r"""Settings for Discovery 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 ``false``, 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 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.v15.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.v15.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, + ) + + 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, + ) + discovery_campaign_settings: DiscoveryCampaignSettings = proto.Field( + proto.MESSAGE, + number=87, + message=DiscoveryCampaignSettings, + ) + 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, + ) + start_date: str = proto.Field( + proto.STRING, + number=63, + optional=True, + ) + campaign_group: str = proto.Field( + proto.STRING, + number=76, + optional=True, + ) + end_date: str = proto.Field( + proto.STRING, + number=64, + 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, + ) + video_brand_safety_suitability: brand_safety_suitability.BrandSafetySuitabilityEnum.BrandSafetySuitability = proto.Field( + proto.ENUM, + number=42, + enum=brand_safety_suitability.BrandSafetySuitabilityEnum.BrandSafetySuitability, + ) + 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, + ) + url_expansion_opt_out: bool = proto.Field( + proto.BOOL, + number=72, + optional=True, + ) + 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, + ) + 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/campaign_asset.py b/google/ads/googleads/v15/resources/types/campaign_asset.py new file mode 100644 index 000000000..9dc2651da --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_asset.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import asset_policy +from google.ads.googleads.v15.enums.types import asset_field_type +from google.ads.googleads.v15.enums.types import asset_link_primary_status +from google.ads.googleads.v15.enums.types import ( + asset_link_primary_status_reason, +) +from google.ads.googleads.v15.enums.types import asset_link_status +from google.ads.googleads.v15.enums.types import asset_source + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.AssetFieldTypeEnum.AssetFieldType): + Immutable. Role that the asset takes under + the linked campaign. Required. + source (google.ads.googleads.v15.enums.types.AssetSourceEnum.AssetSource): + Output only. Source of the campaign asset + link. + status (google.ads.googleads.v15.enums.types.AssetLinkStatusEnum.AssetLinkStatus): + Status of the campaign asset. + primary_status (google.ads.googleads.v15.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.v15.common.types.AssetLinkPrimaryStatusDetails]): + Output only. Provides the details of the + primary status and its associated reasons. + primary_status_reasons (MutableSequence[google.ads.googleads.v15.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/v15/resources/types/campaign_asset_set.py b/google/ads/googleads/v15/resources/types/campaign_asset_set.py new file mode 100644 index 000000000..6cd3766d6 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_asset_set.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import asset_set_link_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/campaign_audience_view.py b/google/ads/googleads/v15/resources/types/campaign_audience_view.py new file mode 100644 index 000000000..cae3287dc --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_audience_view.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/campaign_bid_modifier.py b/google/ads/googleads/v15/resources/types/campaign_bid_modifier.py new file mode 100644 index 000000000..4682b19e5 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_bid_modifier.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import criteria + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/campaign_budget.py b/google/ads/googleads/v15/resources/types/campaign_budget.py new file mode 100644 index 000000000..000924de6 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_budget.py @@ -0,0 +1,278 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import budget_delivery_method +from google.ads.googleads.v15.enums.types import budget_period +from google.ads.googleads.v15.enums.types import budget_status +from google.ads.googleads.v15.enums.types import budget_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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 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. Monthly spend is capped at 30.4 + times this amount. + + This field is a member of `oneof`_ ``_amount_micros``. + total_amount_micros (int): + The lifetime 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. + + This field is a member of `oneof`_ ``_total_amount_micros``. + status (google.ads.googleads.v15.enums.types.BudgetStatusEnum.BudgetStatus): + Output only. The status of this campaign + budget. This field is read-only. + delivery_method (google.ads.googleads.v15.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.v15.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.v15.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/v15/resources/types/campaign_conversion_goal.py b/google/ads/googleads/v15/resources/types/campaign_conversion_goal.py new file mode 100644 index 000000000..3d66df86c --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_conversion_goal.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import conversion_action_category +from google.ads.googleads.v15.enums.types import conversion_origin + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.ConversionActionCategoryEnum.ConversionActionCategory): + The conversion category of this campaign + conversion goal. + origin (google.ads.googleads.v15.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/v15/resources/types/campaign_criterion.py b/google/ads/googleads/v15/resources/types/campaign_criterion.py new file mode 100644 index 000000000..d6f74da76 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_criterion.py @@ -0,0 +1,447 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import criteria +from google.ads.googleads.v15.enums.types import campaign_criterion_status +from google.ads.googleads.v15.enums.types import criterion_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.CriterionTypeEnum.CriterionType): + Output only. The type of the criterion. + status (google.ads.googleads.v15.enums.types.CampaignCriterionStatusEnum.CampaignCriterionStatus): + The status of the criterion. + keyword (google.ads.googleads.v15.common.types.KeywordInfo): + Immutable. Keyword. + + This field is a member of `oneof`_ ``criterion``. + placement (google.ads.googleads.v15.common.types.PlacementInfo): + Immutable. Placement. + + This field is a member of `oneof`_ ``criterion``. + mobile_app_category (google.ads.googleads.v15.common.types.MobileAppCategoryInfo): + Immutable. Mobile app category. + + This field is a member of `oneof`_ ``criterion``. + mobile_application (google.ads.googleads.v15.common.types.MobileApplicationInfo): + Immutable. Mobile application. + + This field is a member of `oneof`_ ``criterion``. + location (google.ads.googleads.v15.common.types.LocationInfo): + Immutable. Location. + + This field is a member of `oneof`_ ``criterion``. + device (google.ads.googleads.v15.common.types.DeviceInfo): + Immutable. Device. + + This field is a member of `oneof`_ ``criterion``. + ad_schedule (google.ads.googleads.v15.common.types.AdScheduleInfo): + Immutable. Ad Schedule. + + This field is a member of `oneof`_ ``criterion``. + age_range (google.ads.googleads.v15.common.types.AgeRangeInfo): + Immutable. Age range. + + This field is a member of `oneof`_ ``criterion``. + gender (google.ads.googleads.v15.common.types.GenderInfo): + Immutable. Gender. + + This field is a member of `oneof`_ ``criterion``. + income_range (google.ads.googleads.v15.common.types.IncomeRangeInfo): + Immutable. Income range. + + This field is a member of `oneof`_ ``criterion``. + parental_status (google.ads.googleads.v15.common.types.ParentalStatusInfo): + Immutable. Parental status. + + This field is a member of `oneof`_ ``criterion``. + user_list (google.ads.googleads.v15.common.types.UserListInfo): + Immutable. User List. + The Similar Audiences sunset starts May 2023. + Refer to + https://ads-developers.googleblog.com/2022/11/announcing-deprecation-and-sunset-of.html + for other options. + + This field is a member of `oneof`_ ``criterion``. + youtube_video (google.ads.googleads.v15.common.types.YouTubeVideoInfo): + Immutable. YouTube Video. + + This field is a member of `oneof`_ ``criterion``. + youtube_channel (google.ads.googleads.v15.common.types.YouTubeChannelInfo): + Immutable. YouTube Channel. + + This field is a member of `oneof`_ ``criterion``. + proximity (google.ads.googleads.v15.common.types.ProximityInfo): + Immutable. Proximity. + + This field is a member of `oneof`_ ``criterion``. + topic (google.ads.googleads.v15.common.types.TopicInfo): + Immutable. Topic. + + This field is a member of `oneof`_ ``criterion``. + listing_scope (google.ads.googleads.v15.common.types.ListingScopeInfo): + Immutable. Listing scope. + + This field is a member of `oneof`_ ``criterion``. + language (google.ads.googleads.v15.common.types.LanguageInfo): + Immutable. Language. + + This field is a member of `oneof`_ ``criterion``. + ip_block (google.ads.googleads.v15.common.types.IpBlockInfo): + Immutable. IpBlock. + + This field is a member of `oneof`_ ``criterion``. + content_label (google.ads.googleads.v15.common.types.ContentLabelInfo): + Immutable. ContentLabel. + + This field is a member of `oneof`_ ``criterion``. + carrier (google.ads.googleads.v15.common.types.CarrierInfo): + Immutable. Carrier. + + This field is a member of `oneof`_ ``criterion``. + user_interest (google.ads.googleads.v15.common.types.UserInterestInfo): + Immutable. User Interest. + + This field is a member of `oneof`_ ``criterion``. + webpage (google.ads.googleads.v15.common.types.WebpageInfo): + Immutable. Webpage. + + This field is a member of `oneof`_ ``criterion``. + operating_system_version (google.ads.googleads.v15.common.types.OperatingSystemVersionInfo): + Immutable. Operating system version. + + This field is a member of `oneof`_ ``criterion``. + mobile_device (google.ads.googleads.v15.common.types.MobileDeviceInfo): + Immutable. Mobile Device. + + This field is a member of `oneof`_ ``criterion``. + location_group (google.ads.googleads.v15.common.types.LocationGroupInfo): + Immutable. Location Group + + This field is a member of `oneof`_ ``criterion``. + custom_affinity (google.ads.googleads.v15.common.types.CustomAffinityInfo): + Immutable. Custom Affinity. + + This field is a member of `oneof`_ ``criterion``. + custom_audience (google.ads.googleads.v15.common.types.CustomAudienceInfo): + Immutable. Custom Audience + + This field is a member of `oneof`_ ``criterion``. + combined_audience (google.ads.googleads.v15.common.types.CombinedAudienceInfo): + Immutable. Combined Audience. + + This field is a member of `oneof`_ ``criterion``. + keyword_theme (google.ads.googleads.v15.common.types.KeywordThemeInfo): + Immutable. Smart Campaign Keyword Theme. + + This field is a member of `oneof`_ ``criterion``. + local_service_id (google.ads.googleads.v15.common.types.LocalServiceIdInfo): + Immutable. GLS service campaign criterion. + + This field is a member of `oneof`_ ``criterion``. + brand_list (google.ads.googleads.v15.common.types.BrandListInfo): + Immutable. Brand list campaign 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/campaign_customizer.py b/google/ads/googleads/v15/resources/types/campaign_customizer.py new file mode 100644 index 000000000..89d5d35e8 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_customizer.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import customizer_value +from google.ads.googleads.v15.enums.types import customizer_value_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.CustomizerValueStatusEnum.CustomizerValueStatus): + Output only. The status of the campaign + customizer. + value (google.ads.googleads.v15.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/v15/resources/types/campaign_draft.py b/google/ads/googleads/v15/resources/types/campaign_draft.py new file mode 100644 index 000000000..6129bf343 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_draft.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import campaign_draft_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/campaign_extension_setting.py b/google/ads/googleads/v15/resources/types/campaign_extension_setting.py new file mode 100644 index 000000000..86c352006 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_extension_setting.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import extension_setting_device +from google.ads.googleads.v15.enums.types import ( + extension_type as gage_extension_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "CampaignExtensionSetting", + }, +) + + +class CampaignExtensionSetting(proto.Message): + r"""A campaign extension setting. + .. _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 extension + setting. CampaignExtensionSetting resource names have the + form: + + ``customers/{customer_id}/campaignExtensionSettings/{campaign_id}~{extension_type}`` + extension_type (google.ads.googleads.v15.enums.types.ExtensionTypeEnum.ExtensionType): + Immutable. The extension type of the customer + extension setting. + campaign (str): + Immutable. The resource name of the campaign. The linked + extension feed items will serve under this campaign. + Campaign resource names have the form: + + ``customers/{customer_id}/campaigns/{campaign_id}`` + + This field is a member of `oneof`_ ``_campaign``. + extension_feed_items (MutableSequence[str]): + The resource names of the extension feed items to serve + under the campaign. ExtensionFeedItem resource names have + the form: + + ``customers/{customer_id}/extensionFeedItems/{feed_item_id}`` + device (google.ads.googleads.v15.enums.types.ExtensionSettingDeviceEnum.ExtensionSettingDevice): + The device for which the extensions will + serve. Optional. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + extension_type: gage_extension_type.ExtensionTypeEnum.ExtensionType = ( + proto.Field( + proto.ENUM, + number=2, + enum=gage_extension_type.ExtensionTypeEnum.ExtensionType, + ) + ) + campaign: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + extension_feed_items: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=7, + ) + device: extension_setting_device.ExtensionSettingDeviceEnum.ExtensionSettingDevice = proto.Field( + proto.ENUM, + number=5, + enum=extension_setting_device.ExtensionSettingDeviceEnum.ExtensionSettingDevice, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/campaign_feed.py b/google/ads/googleads/v15/resources/types/campaign_feed.py new file mode 100644 index 000000000..9a7b15162 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_feed.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import ( + matching_function as gagc_matching_function, +) +from google.ads.googleads.v15.enums.types import feed_link_status +from google.ads.googleads.v15.enums.types import placeholder_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "CampaignFeed", + }, +) + + +class CampaignFeed(proto.Message): + r"""A campaign feed. + .. _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 feed. Campaign + feed resource names have the form: + + \`customers/{customer_id}/campaignFeeds/{campaign_id}~{feed_id} + feed (str): + Immutable. The feed to which the CampaignFeed + belongs. + + This field is a member of `oneof`_ ``_feed``. + campaign (str): + Immutable. The campaign to which the + CampaignFeed belongs. + + This field is a member of `oneof`_ ``_campaign``. + placeholder_types (MutableSequence[google.ads.googleads.v15.enums.types.PlaceholderTypeEnum.PlaceholderType]): + Indicates which placeholder types the feed + may populate under the connected campaign. + Required. + matching_function (google.ads.googleads.v15.common.types.MatchingFunction): + Matching function associated with the + CampaignFeed. The matching function is used to + filter the set of feed items selected. Required. + status (google.ads.googleads.v15.enums.types.FeedLinkStatusEnum.FeedLinkStatus): + Output only. Status of the campaign feed. + This field is read-only. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + feed: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + campaign: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + placeholder_types: MutableSequence[ + placeholder_type.PlaceholderTypeEnum.PlaceholderType + ] = proto.RepeatedField( + proto.ENUM, + number=4, + enum=placeholder_type.PlaceholderTypeEnum.PlaceholderType, + ) + matching_function: gagc_matching_function.MatchingFunction = proto.Field( + proto.MESSAGE, + number=5, + message=gagc_matching_function.MatchingFunction, + ) + status: feed_link_status.FeedLinkStatusEnum.FeedLinkStatus = proto.Field( + proto.ENUM, + number=6, + enum=feed_link_status.FeedLinkStatusEnum.FeedLinkStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/campaign_group.py b/google/ads/googleads/v15/resources/types/campaign_group.py new file mode 100644 index 000000000..b91ad391e --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_group.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import campaign_group_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/campaign_label.py b/google/ads/googleads/v15/resources/types/campaign_label.py new file mode 100644 index 000000000..f4c79fd40 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_label.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/campaign_lifecycle_goal.py b/google/ads/googleads/v15/resources/types/campaign_lifecycle_goal.py new file mode 100644 index 000000000..574ff6f11 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_lifecycle_goal.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import lifecycle_goals +from google.ads.googleads.v15.enums.types import ( + customer_acquisition_optimization_mode, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.enums.types.CustomerAcquisitionOptimizationModeEnum.CustomerAcquisitionOptimizationMode): + Output only. Customer acquisition + optimization mode of this campaign. + value_settings (google.ads.googleads.v15.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/v15/resources/types/campaign_search_term_insight.py b/google/ads/googleads/v15/resources/types/campaign_search_term_insight.py new file mode 100644 index 000000000..64b62e370 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_search_term_insight.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "CampaignSearchTermInsight", + }, +) + + +class CampaignSearchTermInsight(proto.Message): + r"""A Campaign search term view. + 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/v15/resources/types/campaign_shared_set.py b/google/ads/googleads/v15/resources/types/campaign_shared_set.py new file mode 100644 index 000000000..9c1caa631 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_shared_set.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import campaign_shared_set_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/campaign_simulation.py b/google/ads/googleads/v15/resources/types/campaign_simulation.py new file mode 100644 index 000000000..f60d7fc3b --- /dev/null +++ b/google/ads/googleads/v15/resources/types/campaign_simulation.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import simulation +from google.ads.googleads.v15.enums.types import simulation_modification_method +from google.ads.googleads.v15.enums.types import simulation_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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 + - DISCOVERY - 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.v15.enums.types.SimulationTypeEnum.SimulationType): + Output only. The field that the simulation + modifies. + modification_method (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/resources/types/carrier_constant.py b/google/ads/googleads/v15/resources/types/carrier_constant.py new file mode 100644 index 000000000..86389b734 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/carrier_constant.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/change_event.py b/google/ads/googleads/v15/resources/types/change_event.py new file mode 100644 index 000000000..21bcde9a3 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/change_event.py @@ -0,0 +1,361 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import change_client_type +from google.ads.googleads.v15.enums.types import change_event_resource_type +from google.ads.googleads.v15.enums.types import ( + resource_change_operation as gage_resource_change_operation, +) +from google.ads.googleads.v15.resources.types import ad as gagr_ad +from google.ads.googleads.v15.resources.types import ad_group as gagr_ad_group +from google.ads.googleads.v15.resources.types import ( + ad_group_ad as gagr_ad_group_ad, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_asset as gagr_ad_group_asset, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_bid_modifier as gagr_ad_group_bid_modifier, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_criterion as gagr_ad_group_criterion, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_feed as gagr_ad_group_feed, +) +from google.ads.googleads.v15.resources.types import asset as gagr_asset +from google.ads.googleads.v15.resources.types import asset_set as gagr_asset_set +from google.ads.googleads.v15.resources.types import ( + asset_set_asset as gagr_asset_set_asset, +) +from google.ads.googleads.v15.resources.types import campaign as gagr_campaign +from google.ads.googleads.v15.resources.types import ( + campaign_asset as gagr_campaign_asset, +) +from google.ads.googleads.v15.resources.types import ( + campaign_asset_set as gagr_campaign_asset_set, +) +from google.ads.googleads.v15.resources.types import ( + campaign_budget as gagr_campaign_budget, +) +from google.ads.googleads.v15.resources.types import ( + campaign_criterion as gagr_campaign_criterion, +) +from google.ads.googleads.v15.resources.types import ( + campaign_feed as gagr_campaign_feed, +) +from google.ads.googleads.v15.resources.types import ( + customer_asset as gagr_customer_asset, +) +from google.ads.googleads.v15.resources.types import feed as gagr_feed +from google.ads.googleads.v15.resources.types import feed_item as gagr_feed_item +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.resources.types.ChangeEvent.ChangedResource): + Output only. The old resource before the + change. Only changed fields will be populated. + new_resource (google.ads.googleads.v15.resources.types.ChangeEvent.ChangedResource): + Output only. The new resource after the + change. Only changed fields will be populated. + resource_change_operation (google.ads.googleads.v15.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. + feed (str): + Output only. The Feed affected by this + change. + feed_item (str): + Output only. The FeedItem 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.v15.resources.types.Ad): + Output only. Set if change_resource_type == AD. + ad_group (google.ads.googleads.v15.resources.types.AdGroup): + Output only. Set if change_resource_type == AD_GROUP. + ad_group_criterion (google.ads.googleads.v15.resources.types.AdGroupCriterion): + Output only. Set if change_resource_type == + AD_GROUP_CRITERION. + campaign (google.ads.googleads.v15.resources.types.Campaign): + Output only. Set if change_resource_type == CAMPAIGN. + campaign_budget (google.ads.googleads.v15.resources.types.CampaignBudget): + Output only. Set if change_resource_type == CAMPAIGN_BUDGET. + ad_group_bid_modifier (google.ads.googleads.v15.resources.types.AdGroupBidModifier): + Output only. Set if change_resource_type == + AD_GROUP_BID_MODIFIER. + campaign_criterion (google.ads.googleads.v15.resources.types.CampaignCriterion): + Output only. Set if change_resource_type == + CAMPAIGN_CRITERION. + feed (google.ads.googleads.v15.resources.types.Feed): + Output only. Set if change_resource_type == FEED. + feed_item (google.ads.googleads.v15.resources.types.FeedItem): + Output only. Set if change_resource_type == FEED_ITEM. + campaign_feed (google.ads.googleads.v15.resources.types.CampaignFeed): + Output only. Set if change_resource_type == CAMPAIGN_FEED. + ad_group_feed (google.ads.googleads.v15.resources.types.AdGroupFeed): + Output only. Set if change_resource_type == AD_GROUP_FEED. + ad_group_ad (google.ads.googleads.v15.resources.types.AdGroupAd): + Output only. Set if change_resource_type == AD_GROUP_AD. + asset (google.ads.googleads.v15.resources.types.Asset): + Output only. Set if change_resource_type == ASSET. + customer_asset (google.ads.googleads.v15.resources.types.CustomerAsset): + Output only. Set if change_resource_type == CUSTOMER_ASSET. + campaign_asset (google.ads.googleads.v15.resources.types.CampaignAsset): + Output only. Set if change_resource_type == CAMPAIGN_ASSET. + ad_group_asset (google.ads.googleads.v15.resources.types.AdGroupAsset): + Output only. Set if change_resource_type == AD_GROUP_ASSET. + asset_set (google.ads.googleads.v15.resources.types.AssetSet): + Output only. Set if change_resource_type == ASSET_SET. + asset_set_asset (google.ads.googleads.v15.resources.types.AssetSetAsset): + Output only. Set if change_resource_type == ASSET_SET_ASSET. + campaign_asset_set (google.ads.googleads.v15.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, + ) + ) + feed: gagr_feed.Feed = proto.Field( + proto.MESSAGE, + number=8, + message=gagr_feed.Feed, + ) + feed_item: gagr_feed_item.FeedItem = proto.Field( + proto.MESSAGE, + number=9, + message=gagr_feed_item.FeedItem, + ) + campaign_feed: gagr_campaign_feed.CampaignFeed = proto.Field( + proto.MESSAGE, + number=10, + message=gagr_campaign_feed.CampaignFeed, + ) + ad_group_feed: gagr_ad_group_feed.AdGroupFeed = proto.Field( + proto.MESSAGE, + number=11, + message=gagr_ad_group_feed.AdGroupFeed, + ) + 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, + ) + feed: str = proto.Field( + proto.STRING, + number=13, + ) + feed_item: str = proto.Field( + proto.STRING, + number=14, + ) + asset: str = proto.Field( + proto.STRING, + number=20, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/change_status.py b/google/ads/googleads/v15/resources/types/change_status.py new file mode 100644 index 000000000..de489ee6a --- /dev/null +++ b/google/ads/googleads/v15/resources/types/change_status.py @@ -0,0 +1,230 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import change_status_operation +from google.ads.googleads.v15.enums.types import change_status_resource_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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``. + feed (str): + Output only. The Feed affected by this + change. + + This field is a member of `oneof`_ ``_feed``. + feed_item (str): + Output only. The FeedItem affected by this + change. + + This field is a member of `oneof`_ ``_feed_item``. + ad_group_feed (str): + Output only. The AdGroupFeed affected by this + change. + + This field is a member of `oneof`_ ``_ad_group_feed``. + campaign_feed (str): + Output only. The CampaignFeed affected by + this change. + + This field is a member of `oneof`_ ``_campaign_feed``. + 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. + """ + + 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, + ) + feed: str = proto.Field( + proto.STRING, + number=28, + optional=True, + ) + feed_item: str = proto.Field( + proto.STRING, + number=29, + optional=True, + ) + ad_group_feed: str = proto.Field( + proto.STRING, + number=30, + optional=True, + ) + campaign_feed: str = proto.Field( + proto.STRING, + number=31, + 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/click_view.py b/google/ads/googleads/v15/resources/types/click_view.py new file mode 100644 index 000000000..d105b586b --- /dev/null +++ b/google/ads/googleads/v15/resources/types/click_view.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import click_location +from google.ads.googleads.v15.common.types import criteria + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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. + + .. _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.v15.common.types.ClickLocation): + Output only. The location criteria matching + the area of interest associated with the + impression. + location_of_presence (google.ads.googleads.v15.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.v15.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/v15/resources/types/combined_audience.py b/google/ads/googleads/v15/resources/types/combined_audience.py new file mode 100644 index 000000000..e85dc97e1 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/combined_audience.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import combined_audience_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/conversion_action.py b/google/ads/googleads/v15/resources/types/conversion_action.py new file mode 100644 index 000000000..a97fc619d --- /dev/null +++ b/google/ads/googleads/v15/resources/types/conversion_action.py @@ -0,0 +1,437 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import tag_snippet +from google.ads.googleads.v15.enums.types import ( + attribution_model as gage_attribution_model, +) +from google.ads.googleads.v15.enums.types import conversion_action_category +from google.ads.googleads.v15.enums.types import conversion_action_counting_type +from google.ads.googleads.v15.enums.types import conversion_action_status +from google.ads.googleads.v15.enums.types import conversion_action_type +from google.ads.googleads.v15.enums.types import conversion_origin +from google.ads.googleads.v15.enums.types import ( + data_driven_model_status as gage_data_driven_model_status, +) +from google.ads.googleads.v15.enums.types import ( + mobile_app_vendor as gage_mobile_app_vendor, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.ConversionActionStatusEnum.ConversionActionStatus): + The status of this conversion action for + conversion event accrual. + type_ (google.ads.googleads.v15.enums.types.ConversionActionTypeEnum.ConversionActionType): + Immutable. The type of this conversion + action. + origin (google.ads.googleads.v15.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.v15.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.v15.resources.types.ConversionAction.ValueSettings): + Settings related to the value for conversion + events associated with this conversion action. + counting_type (google.ads.googleads.v15.enums.types.ConversionActionCountingTypeEnum.ConversionActionCountingType): + How to count conversion events for the + conversion action. + attribution_model_settings (google.ads.googleads.v15.resources.types.ConversionAction.AttributionModelSettings): + Settings related to this conversion action's + attribution model. + tag_snippets (MutableSequence[google.ads.googleads.v15.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.v15.enums.types.MobileAppVendorEnum.MobileAppVendor): + Output only. Mobile app vendor for an app + conversion action. + firebase_settings (google.ads.googleads.v15.resources.types.ConversionAction.FirebaseSettings): + Output only. Firebase settings for Firebase + conversion types. + third_party_app_analytics_settings (google.ads.googleads.v15.resources.types.ConversionAction.ThirdPartyAppAnalyticsSettings): + Output only. Third Party App Analytics + settings for third party conversion types. + google_analytics_4_settings (google.ads.googleads.v15.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.v15.enums.types.AttributionModelEnum.AttributionModel): + The attribution model type of this conversion + action. + data_driven_model_status (google.ads.googleads.v15.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/v15/resources/types/conversion_custom_variable.py b/google/ads/googleads/v15/resources/types/conversion_custom_variable.py new file mode 100644 index 000000000..33d4a25c2 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/conversion_custom_variable.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + conversion_custom_variable_status, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/conversion_goal_campaign_config.py b/google/ads/googleads/v15/resources/types/conversion_goal_campaign_config.py new file mode 100644 index 000000000..a9134bc58 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/conversion_goal_campaign_config.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + goal_config_level as gage_goal_config_level, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/conversion_value_rule.py b/google/ads/googleads/v15/resources/types/conversion_value_rule.py new file mode 100644 index 000000000..d1ab41f82 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/conversion_value_rule.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import conversion_value_rule_status +from google.ads.googleads.v15.enums.types import value_rule_device_type +from google.ads.googleads.v15.enums.types import ( + value_rule_geo_location_match_type, +) +from google.ads.googleads.v15.enums.types import value_rule_operation + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.resources.types.ConversionValueRule.ValueRuleAction): + Action applied when the rule is triggered. + geo_location_condition (google.ads.googleads.v15.resources.types.ConversionValueRule.ValueRuleGeoLocationCondition): + Condition for Geo location that must be + satisfied for the value rule to apply. + device_condition (google.ads.googleads.v15.resources.types.ConversionValueRule.ValueRuleDeviceCondition): + Condition for device type that must be + satisfied for the value rule to apply. + audience_condition (google.ads.googleads.v15.resources.types.ConversionValueRule.ValueRuleAudienceCondition): + Condition for audience 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.v15.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.v15.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.v15.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.v15.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.v15.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. + The Similar Audiences sunset starts May 2023. + Refer to + https://ads-developers.googleblog.com/2022/11/announcing-deprecation-and-sunset-of.html + for other options. + 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, + ) + + 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, + ) + 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/v15/resources/types/conversion_value_rule_set.py b/google/ads/googleads/v15/resources/types/conversion_value_rule_set.py new file mode 100644 index 000000000..cb3d4e648 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/conversion_value_rule_set.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import conversion_action_category +from google.ads.googleads.v15.enums.types import ( + conversion_value_rule_set_status, +) +from google.ads.googleads.v15.enums.types import value_rule_set_attachment_type +from google.ads.googleads.v15.enums.types import value_rule_set_dimension + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "ConversionValueRuleSet", + }, +) + + +class ConversionValueRuleSet(proto.Message): + r"""A conversion value rule set + 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.v15.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.v15.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.v15.enums.types.ConversionValueRuleSetStatusEnum.ConversionValueRuleSetStatus): + Output only. The status of the conversion value rule set. + \*\* Read-only \*\* + conversion_action_categories (MutableSequence[google.ads.googleads.v15.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/v15/resources/types/currency_constant.py b/google/ads/googleads/v15/resources/types/currency_constant.py new file mode 100644 index 000000000..e072029f7 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/currency_constant.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/custom_audience.py b/google/ads/googleads/v15/resources/types/custom_audience.py new file mode 100644 index 000000000..463bfbede --- /dev/null +++ b/google/ads/googleads/v15/resources/types/custom_audience.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import custom_audience_member_type +from google.ads.googleads.v15.enums.types import custom_audience_status +from google.ads.googleads.v15.enums.types import custom_audience_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "CustomAudience", + "CustomAudienceMember", + }, +) + + +class CustomAudience(proto.Message): + r"""A custom audience. This is a list of users by interest. + 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.v15.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.v15.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.v15.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.v15.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/v15/resources/types/custom_conversion_goal.py b/google/ads/googleads/v15/resources/types/custom_conversion_goal.py new file mode 100644 index 000000000..8f7d2960b --- /dev/null +++ b/google/ads/googleads/v15/resources/types/custom_conversion_goal.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import custom_conversion_goal_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/custom_interest.py b/google/ads/googleads/v15/resources/types/custom_interest.py new file mode 100644 index 000000000..8cf316091 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/custom_interest.py @@ -0,0 +1,145 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import custom_interest_member_type +from google.ads.googleads.v15.enums.types import custom_interest_status +from google.ads.googleads.v15.enums.types import custom_interest_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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.v15.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/v15/resources/types/customer.py b/google/ads/googleads/v15/resources/types/customer.py new file mode 100644 index 000000000..c9940f806 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer.py @@ -0,0 +1,577 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import conversion_tracking_status_enum +from google.ads.googleads.v15.enums.types import ( + customer_pay_per_conversion_eligibility_failure_reason, +) +from google.ads.googleads.v15.enums.types import customer_status +from google.ads.googleads.v15.enums.types import ( + local_services_verification_status, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "Customer", + "CallReportingSetting", + "ConversionTrackingSetting", + "RemarketingSetting", + "CustomerAgreementSetting", + "LocalServicesSettings", + "GranularLicenseStatus", + "GranularInsuranceStatus", + }, +) + + +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. + + 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.v15.resources.types.CallReportingSetting): + Call reporting setting for a customer. Only mutable in an + ``update`` operation. + conversion_tracking_setting (google.ads.googleads.v15.resources.types.ConversionTrackingSetting): + Output only. Conversion tracking setting for + a customer. + remarketing_setting (google.ads.googleads.v15.resources.types.RemarketingSetting): + Output only. Remarketing setting for a + customer. + pay_per_conversion_eligibility_failure_reasons (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.resources.types.CustomerAgreementSetting): + Output only. Customer Agreement Setting for a + customer. + local_services_settings (google.ads.googleads.v15.resources.types.LocalServicesSettings): + Output only. Settings for Local Services + customer. + """ + + 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", + ) + + +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.v15.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): + Output only. 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.v15.resources.types.GranularLicenseStatus]): + Output only. A read-only list of geo vertical + level license statuses. + granular_insurance_statuses (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/customer_asset.py b/google/ads/googleads/v15/resources/types/customer_asset.py new file mode 100644 index 000000000..6dff98602 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_asset.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import asset_policy +from google.ads.googleads.v15.enums.types import asset_field_type +from google.ads.googleads.v15.enums.types import asset_link_primary_status +from google.ads.googleads.v15.enums.types import ( + asset_link_primary_status_reason, +) +from google.ads.googleads.v15.enums.types import asset_link_status +from google.ads.googleads.v15.enums.types import asset_source + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.AssetFieldTypeEnum.AssetFieldType): + Required. Immutable. Role that the asset + takes for the customer link. + source (google.ads.googleads.v15.enums.types.AssetSourceEnum.AssetSource): + Output only. Source of the customer asset + link. + status (google.ads.googleads.v15.enums.types.AssetLinkStatusEnum.AssetLinkStatus): + Status of the customer asset. + primary_status (google.ads.googleads.v15.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.v15.common.types.AssetLinkPrimaryStatusDetails]): + Output only. Provides the details of the + primary status and its associated reasons. + primary_status_reasons (MutableSequence[google.ads.googleads.v15.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/v15/resources/types/customer_asset_set.py b/google/ads/googleads/v15/resources/types/customer_asset_set.py new file mode 100644 index 000000000..608dbd270 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_asset_set.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import asset_set_link_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/customer_client.py b/google/ads/googleads/v15/resources/types/customer_client.py new file mode 100644 index 000000000..d02570503 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_client.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import customer_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/customer_client_link.py b/google/ads/googleads/v15/resources/types/customer_client_link.py new file mode 100644 index 000000000..0f7a977fa --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_client_link.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import manager_link_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/customer_conversion_goal.py b/google/ads/googleads/v15/resources/types/customer_conversion_goal.py new file mode 100644 index 000000000..98f9e7f1e --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_conversion_goal.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import conversion_action_category +from google.ads.googleads.v15.enums.types import conversion_origin + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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/v15/resources/types/customer_customizer.py b/google/ads/googleads/v15/resources/types/customer_customizer.py new file mode 100644 index 000000000..f691ffe8c --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_customizer.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import customizer_value +from google.ads.googleads.v15.enums.types import customizer_value_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.CustomizerValueStatusEnum.CustomizerValueStatus): + Output only. The status of the customer + customizer attribute. + value (google.ads.googleads.v15.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/v15/resources/types/customer_extension_setting.py b/google/ads/googleads/v15/resources/types/customer_extension_setting.py new file mode 100644 index 000000000..49a7305c1 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_extension_setting.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import extension_setting_device +from google.ads.googleads.v15.enums.types import ( + extension_type as gage_extension_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "CustomerExtensionSetting", + }, +) + + +class CustomerExtensionSetting(proto.Message): + r"""A customer extension setting. + Attributes: + resource_name (str): + Immutable. The resource name of the customer extension + setting. CustomerExtensionSetting resource names have the + form: + + ``customers/{customer_id}/customerExtensionSettings/{extension_type}`` + extension_type (google.ads.googleads.v15.enums.types.ExtensionTypeEnum.ExtensionType): + Immutable. The extension type of the customer + extension setting. + extension_feed_items (MutableSequence[str]): + The resource names of the extension feed items to serve + under the customer. ExtensionFeedItem resource names have + the form: + + ``customers/{customer_id}/extensionFeedItems/{feed_item_id}`` + device (google.ads.googleads.v15.enums.types.ExtensionSettingDeviceEnum.ExtensionSettingDevice): + The device for which the extensions will + serve. Optional. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + extension_type: gage_extension_type.ExtensionTypeEnum.ExtensionType = ( + proto.Field( + proto.ENUM, + number=2, + enum=gage_extension_type.ExtensionTypeEnum.ExtensionType, + ) + ) + extension_feed_items: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=5, + ) + device: extension_setting_device.ExtensionSettingDeviceEnum.ExtensionSettingDevice = proto.Field( + proto.ENUM, + number=4, + enum=extension_setting_device.ExtensionSettingDeviceEnum.ExtensionSettingDevice, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/customer_feed.py b/google/ads/googleads/v15/resources/types/customer_feed.py new file mode 100644 index 000000000..9b4bbf9ee --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_feed.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import ( + matching_function as gagc_matching_function, +) +from google.ads.googleads.v15.enums.types import feed_link_status +from google.ads.googleads.v15.enums.types import placeholder_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "CustomerFeed", + }, +) + + +class CustomerFeed(proto.Message): + r"""A customer feed. + .. _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 feed. Customer + feed resource names have the form: + + ``customers/{customer_id}/customerFeeds/{feed_id}`` + feed (str): + Immutable. The feed being linked to the + customer. + + This field is a member of `oneof`_ ``_feed``. + placeholder_types (MutableSequence[google.ads.googleads.v15.enums.types.PlaceholderTypeEnum.PlaceholderType]): + Indicates which placeholder types the feed + may populate under the connected customer. + Required. + matching_function (google.ads.googleads.v15.common.types.MatchingFunction): + Matching function associated with the + CustomerFeed. The matching function is used to + filter the set of feed items selected. Required. + status (google.ads.googleads.v15.enums.types.FeedLinkStatusEnum.FeedLinkStatus): + Output only. Status of the customer feed. + This field is read-only. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + feed: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + placeholder_types: MutableSequence[ + placeholder_type.PlaceholderTypeEnum.PlaceholderType + ] = proto.RepeatedField( + proto.ENUM, + number=3, + enum=placeholder_type.PlaceholderTypeEnum.PlaceholderType, + ) + matching_function: gagc_matching_function.MatchingFunction = proto.Field( + proto.MESSAGE, + number=4, + message=gagc_matching_function.MatchingFunction, + ) + status: feed_link_status.FeedLinkStatusEnum.FeedLinkStatus = proto.Field( + proto.ENUM, + number=5, + enum=feed_link_status.FeedLinkStatusEnum.FeedLinkStatus, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/customer_label.py b/google/ads/googleads/v15/resources/types/customer_label.py new file mode 100644 index 000000000..a4030c49b --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_label.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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. Read + only. + + This field is a member of `oneof`_ ``_customer``. + label (str): + Output only. The resource name of the label + assigned to the customer. + 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/v15/resources/types/customer_lifecycle_goal.py b/google/ads/googleads/v15/resources/types/customer_lifecycle_goal.py new file mode 100644 index 000000000..2ea7daa53 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_lifecycle_goal.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import lifecycle_goals + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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`` + lifecycle_goal_customer_definition_settings (google.ads.googleads.v15.resources.types.CustomerLifecycleGoal.LifecycleGoalCustomerDefinitionSettings): + Output only. Common lifecycle goal settings + shared among different types of lifecycle goals. + customer_acquisition_goal_value_settings (google.ads.googleads.v15.common.types.LifecycleGoalValueSettings): + Output only. Customer acquisition goal + customer level value settings. + """ + + class LifecycleGoalCustomerDefinitionSettings(proto.Message): + r"""Lifecycle goal common settings, including existing user lists + and existing high lifetime value user lists, shared among + different types of lifecycle goals. + + Attributes: + existing_user_lists (MutableSequence[str]): + Output only. User lists which represent + existing customers. + high_lifetime_value_user_lists (MutableSequence[str]): + Output only. User lists which represent + customers of high lifetime value. In current + stage, high lifetime value feature is in beta + and this field is read-only. + """ + + existing_user_lists: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + high_lifetime_value_user_lists: MutableSequence[ + str + ] = proto.RepeatedField( + proto.STRING, + number=2, + ) + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + lifecycle_goal_customer_definition_settings: LifecycleGoalCustomerDefinitionSettings = proto.Field( + proto.MESSAGE, + number=2, + message=LifecycleGoalCustomerDefinitionSettings, + ) + customer_acquisition_goal_value_settings: lifecycle_goals.LifecycleGoalValueSettings = proto.Field( + proto.MESSAGE, + number=3, + message=lifecycle_goals.LifecycleGoalValueSettings, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/customer_manager_link.py b/google/ads/googleads/v15/resources/types/customer_manager_link.py new file mode 100644 index 000000000..9ed2ffa1d --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_manager_link.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import manager_link_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/customer_negative_criterion.py b/google/ads/googleads/v15/resources/types/customer_negative_criterion.py new file mode 100644 index 000000000..87ed76e22 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_negative_criterion.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import criteria +from google.ads.googleads.v15.enums.types import criterion_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.CriterionTypeEnum.CriterionType): + Output only. The type of the criterion. + content_label (google.ads.googleads.v15.common.types.ContentLabelInfo): + Immutable. ContentLabel. + + This field is a member of `oneof`_ ``criterion``. + mobile_application (google.ads.googleads.v15.common.types.MobileApplicationInfo): + Immutable. MobileApplication. + + This field is a member of `oneof`_ ``criterion``. + mobile_app_category (google.ads.googleads.v15.common.types.MobileAppCategoryInfo): + Immutable. MobileAppCategory. + + This field is a member of `oneof`_ ``criterion``. + placement (google.ads.googleads.v15.common.types.PlacementInfo): + Immutable. Placement. + + This field is a member of `oneof`_ ``criterion``. + youtube_video (google.ads.googleads.v15.common.types.YouTubeVideoInfo): + Immutable. YouTube Video. + + This field is a member of `oneof`_ ``criterion``. + youtube_channel (google.ads.googleads.v15.common.types.YouTubeChannelInfo): + Immutable. YouTube Channel. + + This field is a member of `oneof`_ ``criterion``. + negative_keyword_list (google.ads.googleads.v15.common.types.NegativeKeywordListInfo): + Immutable. NegativeKeywordList. + + 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/customer_search_term_insight.py b/google/ads/googleads/v15/resources/types/customer_search_term_insight.py new file mode 100644 index 000000000..b4ea67aee --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_search_term_insight.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "CustomerSearchTermInsight", + }, +) + + +class CustomerSearchTermInsight(proto.Message): + r"""A Customer search term view. + 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/v15/resources/types/customer_sk_ad_network_conversion_value_schema.py b/google/ads/googleads/v15/resources/types/customer_sk_ad_network_conversion_value_schema.py new file mode 100644 index 000000000..53b75a72b --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_sk_ad_network_conversion_value_schema.py @@ -0,0 +1,257 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.resources.types.CustomerSkAdNetworkConversionValueSchema.SkAdNetworkConversionValueSchema.FineGrainedConversionValueMappings]): + Output only. Fine grained conversion value + mappings. + """ + + 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.v15.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 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.v15.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.v15.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.v15.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", + ) + + 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/v15/resources/types/customer_user_access.py b/google/ads/googleads/v15/resources/types/customer_user_access.py new file mode 100644 index 000000000..c49293b22 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_user_access.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import access_role as gage_access_role + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/customer_user_access_invitation.py b/google/ads/googleads/v15/resources/types/customer_user_access_invitation.py new file mode 100644 index 000000000..0457e5c7c --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customer_user_access_invitation.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import access_invitation_status +from google.ads.googleads.v15.enums.types import access_role as gage_access_role + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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/v15/resources/types/customizer_attribute.py b/google/ads/googleads/v15/resources/types/customizer_attribute.py new file mode 100644 index 000000000..914ba4adb --- /dev/null +++ b/google/ads/googleads/v15/resources/types/customizer_attribute.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import customizer_attribute_status +from google.ads.googleads.v15.enums.types import customizer_attribute_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.CustomizerAttributeTypeEnum.CustomizerAttributeType): + Immutable. The type of the customizer + attribute. + status (google.ads.googleads.v15.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/v15/resources/types/detail_placement_view.py b/google/ads/googleads/v15/resources/types/detail_placement_view.py new file mode 100644 index 000000000..fa5b44153 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/detail_placement_view.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + placement_type as gage_placement_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "DetailPlacementView", + }, +) + + +class DetailPlacementView(proto.Message): + r"""A view with metrics aggregated by ad group and URL or YouTube + video. + + .. _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.v15.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/v15/resources/types/detailed_demographic.py b/google/ads/googleads/v15/resources/types/detailed_demographic.py new file mode 100644 index 000000000..4a102db5d --- /dev/null +++ b/google/ads/googleads/v15/resources/types/detailed_demographic.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import ( + criterion_category_availability, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/display_keyword_view.py b/google/ads/googleads/v15/resources/types/display_keyword_view.py new file mode 100644 index 000000000..8c0cd9035 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/display_keyword_view.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "DisplayKeywordView", + }, +) + + +class DisplayKeywordView(proto.Message): + r"""A display keyword view. + 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/v15/resources/types/distance_view.py b/google/ads/googleads/v15/resources/types/distance_view.py new file mode 100644 index 000000000..9cc9a26a6 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/distance_view.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + distance_bucket as gage_distance_bucket, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/domain_category.py b/google/ads/googleads/v15/resources/types/domain_category.py new file mode 100644 index 000000000..8d706e93a --- /dev/null +++ b/google/ads/googleads/v15/resources/types/domain_category.py @@ -0,0 +1,145 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/dynamic_search_ads_search_term_view.py b/google/ads/googleads/v15/resources/types/dynamic_search_ads_search_term_view.py new file mode 100644 index 000000000..2f0401f98 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/dynamic_search_ads_search_term_view.py @@ -0,0 +1,127 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/expanded_landing_page_view.py b/google/ads/googleads/v15/resources/types/expanded_landing_page_view.py new file mode 100644 index 000000000..de9f8ae53 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/expanded_landing_page_view.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/experiment.py b/google/ads/googleads/v15/resources/types/experiment.py new file mode 100644 index 000000000..c0832ae9b --- /dev/null +++ b/google/ads/googleads/v15/resources/types/experiment.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import metric_goal +from google.ads.googleads.v15.enums.types import async_action_status +from google.ads.googleads.v15.enums.types import experiment_status +from google.ads.googleads.v15.enums.types import experiment_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.ExperimentTypeEnum.ExperimentType): + Required. The product/feature that uses this + experiment. + status (google.ads.googleads.v15.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.v15.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.v15.enums.types.AsyncActionStatusEnum.AsyncActionStatus): + Output only. The status of the experiment + promotion process. + """ + + 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/experiment_arm.py b/google/ads/googleads/v15/resources/types/experiment_arm.py new file mode 100644 index 000000000..c7d277efa --- /dev/null +++ b/google/ads/googleads/v15/resources/types/experiment_arm.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/extension_feed_item.py b/google/ads/googleads/v15/resources/types/extension_feed_item.py new file mode 100644 index 000000000..06063a95c --- /dev/null +++ b/google/ads/googleads/v15/resources/types/extension_feed_item.py @@ -0,0 +1,301 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import criteria +from google.ads.googleads.v15.common.types import extensions +from google.ads.googleads.v15.enums.types import ( + extension_type as gage_extension_type, +) +from google.ads.googleads.v15.enums.types import feed_item_status +from google.ads.googleads.v15.enums.types import feed_item_target_device + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "ExtensionFeedItem", + }, +) + + +class ExtensionFeedItem(proto.Message): + r"""An extension feed 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: + resource_name (str): + Immutable. The resource name of the extension feed item. + Extension feed item resource names have the form: + + ``customers/{customer_id}/extensionFeedItems/{feed_item_id}`` + id (int): + Output only. The ID of this feed item. + Read-only. + + This field is a member of `oneof`_ ``_id``. + extension_type (google.ads.googleads.v15.enums.types.ExtensionTypeEnum.ExtensionType): + Output only. The extension type of the + extension feed item. This field is read-only. + start_date_time (str): + Start time in which this feed item is + effective and can begin serving. The time is in + the customer's time zone. 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`_ ``_start_date_time``. + end_date_time (str): + End time in which this feed item is no longer + effective and will stop serving. The time is in + the customer's time zone. 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`_ ``_end_date_time``. + ad_schedules (MutableSequence[google.ads.googleads.v15.common.types.AdScheduleInfo]): + List of non-overlapping schedules specifying + all time intervals for which the feed item may + serve. There can be a maximum of 6 schedules per + day. + device (google.ads.googleads.v15.enums.types.FeedItemTargetDeviceEnum.FeedItemTargetDevice): + The targeted device. + targeted_geo_target_constant (str): + The targeted geo target constant. + + This field is a member of `oneof`_ ``_targeted_geo_target_constant``. + targeted_keyword (google.ads.googleads.v15.common.types.KeywordInfo): + The targeted keyword. + status (google.ads.googleads.v15.enums.types.FeedItemStatusEnum.FeedItemStatus): + Output only. Status of the feed item. + This field is read-only. + sitelink_feed_item (google.ads.googleads.v15.common.types.SitelinkFeedItem): + Sitelink. + + This field is a member of `oneof`_ ``extension``. + structured_snippet_feed_item (google.ads.googleads.v15.common.types.StructuredSnippetFeedItem): + Structured snippet extension. + + This field is a member of `oneof`_ ``extension``. + app_feed_item (google.ads.googleads.v15.common.types.AppFeedItem): + App extension. + + This field is a member of `oneof`_ ``extension``. + call_feed_item (google.ads.googleads.v15.common.types.CallFeedItem): + Call extension. + + This field is a member of `oneof`_ ``extension``. + callout_feed_item (google.ads.googleads.v15.common.types.CalloutFeedItem): + Callout extension. + + This field is a member of `oneof`_ ``extension``. + text_message_feed_item (google.ads.googleads.v15.common.types.TextMessageFeedItem): + Text message extension. + + This field is a member of `oneof`_ ``extension``. + price_feed_item (google.ads.googleads.v15.common.types.PriceFeedItem): + Price extension. + + This field is a member of `oneof`_ ``extension``. + promotion_feed_item (google.ads.googleads.v15.common.types.PromotionFeedItem): + Promotion extension. + + This field is a member of `oneof`_ ``extension``. + location_feed_item (google.ads.googleads.v15.common.types.LocationFeedItem): + Output only. Location extension. Locations + are synced from a Business Profile into a feed. + This field is read-only. + + This field is a member of `oneof`_ ``extension``. + affiliate_location_feed_item (google.ads.googleads.v15.common.types.AffiliateLocationFeedItem): + Output only. Affiliate location extension. + Feed locations are populated by Google Ads based + on a chain ID. This field is read-only. + + This field is a member of `oneof`_ ``extension``. + hotel_callout_feed_item (google.ads.googleads.v15.common.types.HotelCalloutFeedItem): + Hotel Callout extension. + + This field is a member of `oneof`_ ``extension``. + image_feed_item (google.ads.googleads.v15.common.types.ImageFeedItem): + Immutable. Advertiser provided image + extension. + + This field is a member of `oneof`_ ``extension``. + targeted_campaign (str): + The targeted campaign. + + This field is a member of `oneof`_ ``serving_resource_targeting``. + targeted_ad_group (str): + The targeted ad group. + + This field is a member of `oneof`_ ``serving_resource_targeting``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + id: int = proto.Field( + proto.INT64, + number=25, + optional=True, + ) + extension_type: gage_extension_type.ExtensionTypeEnum.ExtensionType = ( + proto.Field( + proto.ENUM, + number=13, + enum=gage_extension_type.ExtensionTypeEnum.ExtensionType, + ) + ) + start_date_time: str = proto.Field( + proto.STRING, + number=26, + optional=True, + ) + end_date_time: str = proto.Field( + proto.STRING, + number=27, + optional=True, + ) + ad_schedules: MutableSequence[ + criteria.AdScheduleInfo + ] = proto.RepeatedField( + proto.MESSAGE, + number=16, + message=criteria.AdScheduleInfo, + ) + device: feed_item_target_device.FeedItemTargetDeviceEnum.FeedItemTargetDevice = proto.Field( + proto.ENUM, + number=17, + enum=feed_item_target_device.FeedItemTargetDeviceEnum.FeedItemTargetDevice, + ) + targeted_geo_target_constant: str = proto.Field( + proto.STRING, + number=30, + optional=True, + ) + targeted_keyword: criteria.KeywordInfo = proto.Field( + proto.MESSAGE, + number=22, + message=criteria.KeywordInfo, + ) + status: feed_item_status.FeedItemStatusEnum.FeedItemStatus = proto.Field( + proto.ENUM, + number=4, + enum=feed_item_status.FeedItemStatusEnum.FeedItemStatus, + ) + sitelink_feed_item: extensions.SitelinkFeedItem = proto.Field( + proto.MESSAGE, + number=2, + oneof="extension", + message=extensions.SitelinkFeedItem, + ) + structured_snippet_feed_item: extensions.StructuredSnippetFeedItem = ( + proto.Field( + proto.MESSAGE, + number=3, + oneof="extension", + message=extensions.StructuredSnippetFeedItem, + ) + ) + app_feed_item: extensions.AppFeedItem = proto.Field( + proto.MESSAGE, + number=7, + oneof="extension", + message=extensions.AppFeedItem, + ) + call_feed_item: extensions.CallFeedItem = proto.Field( + proto.MESSAGE, + number=8, + oneof="extension", + message=extensions.CallFeedItem, + ) + callout_feed_item: extensions.CalloutFeedItem = proto.Field( + proto.MESSAGE, + number=9, + oneof="extension", + message=extensions.CalloutFeedItem, + ) + text_message_feed_item: extensions.TextMessageFeedItem = proto.Field( + proto.MESSAGE, + number=10, + oneof="extension", + message=extensions.TextMessageFeedItem, + ) + price_feed_item: extensions.PriceFeedItem = proto.Field( + proto.MESSAGE, + number=11, + oneof="extension", + message=extensions.PriceFeedItem, + ) + promotion_feed_item: extensions.PromotionFeedItem = proto.Field( + proto.MESSAGE, + number=12, + oneof="extension", + message=extensions.PromotionFeedItem, + ) + location_feed_item: extensions.LocationFeedItem = proto.Field( + proto.MESSAGE, + number=14, + oneof="extension", + message=extensions.LocationFeedItem, + ) + affiliate_location_feed_item: extensions.AffiliateLocationFeedItem = ( + proto.Field( + proto.MESSAGE, + number=15, + oneof="extension", + message=extensions.AffiliateLocationFeedItem, + ) + ) + hotel_callout_feed_item: extensions.HotelCalloutFeedItem = proto.Field( + proto.MESSAGE, + number=23, + oneof="extension", + message=extensions.HotelCalloutFeedItem, + ) + image_feed_item: extensions.ImageFeedItem = proto.Field( + proto.MESSAGE, + number=31, + oneof="extension", + message=extensions.ImageFeedItem, + ) + targeted_campaign: str = proto.Field( + proto.STRING, + number=28, + oneof="serving_resource_targeting", + ) + targeted_ad_group: str = proto.Field( + proto.STRING, + number=29, + oneof="serving_resource_targeting", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/feed.py b/google/ads/googleads/v15/resources/types/feed.py new file mode 100644 index 000000000..1793dfab9 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/feed.py @@ -0,0 +1,360 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + affiliate_location_feed_relationship_type, +) +from google.ads.googleads.v15.enums.types import feed_attribute_type +from google.ads.googleads.v15.enums.types import feed_origin +from google.ads.googleads.v15.enums.types import feed_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "Feed", + "FeedAttribute", + "FeedAttributeOperation", + }, +) + + +class Feed(proto.Message): + r"""A feed. + 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 feed. Feed resource + names have the form: + + ``customers/{customer_id}/feeds/{feed_id}`` + id (int): + Output only. The ID of the feed. + This field is read-only. + + This field is a member of `oneof`_ ``_id``. + name (str): + Immutable. Name of the feed. Required. + + This field is a member of `oneof`_ ``_name``. + attributes (MutableSequence[google.ads.googleads.v15.resources.types.FeedAttribute]): + The Feed's attributes. Required on CREATE, unless + system_feed_generation_data is provided, in which case + Google Ads will update the feed with the correct attributes. + Disallowed on UPDATE. Use attribute_operations to add new + attributes. + attribute_operations (MutableSequence[google.ads.googleads.v15.resources.types.FeedAttributeOperation]): + The list of operations changing the feed + attributes. Attributes can only be added, not + removed. + origin (google.ads.googleads.v15.enums.types.FeedOriginEnum.FeedOrigin): + Immutable. Specifies who manages the + FeedAttributes for the Feed. + status (google.ads.googleads.v15.enums.types.FeedStatusEnum.FeedStatus): + Output only. Status of the feed. + This field is read-only. + places_location_feed_data (google.ads.googleads.v15.resources.types.Feed.PlacesLocationFeedData): + Data used to configure a location feed + populated from Business Profile. + + This field is a member of `oneof`_ ``system_feed_generation_data``. + affiliate_location_feed_data (google.ads.googleads.v15.resources.types.Feed.AffiliateLocationFeedData): + Data used to configure an affiliate location + feed populated with the specified chains. + + This field is a member of `oneof`_ ``system_feed_generation_data``. + """ + + class PlacesLocationFeedData(proto.Message): + r"""Data used to configure a location feed populated from + Business Profile. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + oauth_info (google.ads.googleads.v15.resources.types.Feed.PlacesLocationFeedData.OAuthInfo): + Immutable. Required authentication token + (from OAuth API) for the email. This field can + only be specified in a create request. All its + subfields are not selectable. + email_address (str): + Email address of a Business Profile or email + address of a manager of the Business Profile. + Required. + + This field is a member of `oneof`_ ``_email_address``. + business_account_id (str): + Plus page ID of the managed business whose locations should + be used. If this field is not set, then all businesses + accessible by the user (specified by email_address) are + used. This field is mutate-only and is not selectable. + business_name_filter (str): + Used to filter Business Profile listings by business name. + If business_name_filter is set, only listings with a + matching business name are candidates to be sync'd into + FeedItems. + + This field is a member of `oneof`_ ``_business_name_filter``. + category_filters (MutableSequence[str]): + Used to filter Business Profile listings by categories. If + entries exist in category_filters, only listings that belong + to any of the categories are candidates to be sync'd into + FeedItems. If no entries exist in category_filters, then all + listings are candidates for syncing. + label_filters (MutableSequence[str]): + Used to filter Business Profile listings by labels. If + entries exist in label_filters, only listings that has any + of the labels set are candidates to be synchronized into + FeedItems. If no entries exist in label_filters, then all + listings are candidates for syncing. + """ + + class OAuthInfo(proto.Message): + r"""Data used for authorization using OAuth. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + http_method (str): + The HTTP method used to obtain authorization. + + This field is a member of `oneof`_ ``_http_method``. + http_request_url (str): + The HTTP request URL used to obtain + authorization. + + This field is a member of `oneof`_ ``_http_request_url``. + http_authorization_header (str): + The HTTP authorization header used to obtain + authorization. + + This field is a member of `oneof`_ ``_http_authorization_header``. + """ + + http_method: str = proto.Field( + proto.STRING, + number=4, + optional=True, + ) + http_request_url: str = proto.Field( + proto.STRING, + number=5, + optional=True, + ) + http_authorization_header: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + + oauth_info: "Feed.PlacesLocationFeedData.OAuthInfo" = proto.Field( + proto.MESSAGE, + number=1, + message="Feed.PlacesLocationFeedData.OAuthInfo", + ) + email_address: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + business_account_id: str = proto.Field( + proto.STRING, + number=8, + ) + business_name_filter: str = proto.Field( + proto.STRING, + number=9, + optional=True, + ) + category_filters: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=11, + ) + label_filters: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=12, + ) + + class AffiliateLocationFeedData(proto.Message): + r"""Data used to configure an affiliate location feed populated + with the specified chains. + + Attributes: + chain_ids (MutableSequence[int]): + The list of chains that the affiliate + location feed will sync the locations from. + relationship_type (google.ads.googleads.v15.enums.types.AffiliateLocationFeedRelationshipTypeEnum.AffiliateLocationFeedRelationshipType): + The relationship the chains have with the + advertiser. + """ + + chain_ids: MutableSequence[int] = proto.RepeatedField( + proto.INT64, + number=3, + ) + relationship_type: affiliate_location_feed_relationship_type.AffiliateLocationFeedRelationshipTypeEnum.AffiliateLocationFeedRelationshipType = proto.Field( + proto.ENUM, + number=2, + enum=affiliate_location_feed_relationship_type.AffiliateLocationFeedRelationshipTypeEnum.AffiliateLocationFeedRelationshipType, + ) + + 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, + ) + attributes: MutableSequence["FeedAttribute"] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="FeedAttribute", + ) + attribute_operations: MutableSequence[ + "FeedAttributeOperation" + ] = proto.RepeatedField( + proto.MESSAGE, + number=9, + message="FeedAttributeOperation", + ) + origin: feed_origin.FeedOriginEnum.FeedOrigin = proto.Field( + proto.ENUM, + number=5, + enum=feed_origin.FeedOriginEnum.FeedOrigin, + ) + status: feed_status.FeedStatusEnum.FeedStatus = proto.Field( + proto.ENUM, + number=8, + enum=feed_status.FeedStatusEnum.FeedStatus, + ) + places_location_feed_data: PlacesLocationFeedData = proto.Field( + proto.MESSAGE, + number=6, + oneof="system_feed_generation_data", + message=PlacesLocationFeedData, + ) + affiliate_location_feed_data: AffiliateLocationFeedData = proto.Field( + proto.MESSAGE, + number=7, + oneof="system_feed_generation_data", + message=AffiliateLocationFeedData, + ) + + +class FeedAttribute(proto.Message): + r"""FeedAttributes define the types of data expected to be + present in a Feed. A single FeedAttribute specifies the expected + type of the FeedItemAttributes with the same FeedAttributeId. + Optionally, a FeedAttribute can be marked as being part of a + FeedItem's unique key. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + id (int): + ID of the attribute. + + This field is a member of `oneof`_ ``_id``. + name (str): + The name of the attribute. Required. + + This field is a member of `oneof`_ ``_name``. + type_ (google.ads.googleads.v15.enums.types.FeedAttributeTypeEnum.FeedAttributeType): + Data type for feed attribute. Required. + is_part_of_key (bool): + Indicates that data corresponding to this attribute is part + of a FeedItem's unique key. It defaults to false if it is + unspecified. Note that a unique key is not required in a + Feed's schema, in which case the FeedItems must be + referenced by their feed_item_id. + + This field is a member of `oneof`_ ``_is_part_of_key``. + """ + + id: int = proto.Field( + proto.INT64, + number=5, + optional=True, + ) + name: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + type_: feed_attribute_type.FeedAttributeTypeEnum.FeedAttributeType = ( + proto.Field( + proto.ENUM, + number=3, + enum=feed_attribute_type.FeedAttributeTypeEnum.FeedAttributeType, + ) + ) + is_part_of_key: bool = proto.Field( + proto.BOOL, + number=7, + optional=True, + ) + + +class FeedAttributeOperation(proto.Message): + r"""Operation to be performed on a feed attribute list in a + mutate. + + Attributes: + operator (google.ads.googleads.v15.resources.types.FeedAttributeOperation.Operator): + Output only. Type of list operation to + perform. + value (google.ads.googleads.v15.resources.types.FeedAttribute): + Output only. The feed attribute being added + to the list. + """ + + class Operator(proto.Enum): + r"""The operator.""" + UNSPECIFIED = 0 + UNKNOWN = 1 + ADD = 2 + + operator: Operator = proto.Field( + proto.ENUM, + number=1, + enum=Operator, + ) + value: "FeedAttribute" = proto.Field( + proto.MESSAGE, + number=2, + message="FeedAttribute", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/feed_item.py b/google/ads/googleads/v15/resources/types/feed_item.py new file mode 100644 index 000000000..5c049ff18 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/feed_item.py @@ -0,0 +1,424 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import custom_parameter +from google.ads.googleads.v15.common.types import feed_common +from google.ads.googleads.v15.common.types import policy +from google.ads.googleads.v15.enums.types import ( + feed_item_quality_approval_status, +) +from google.ads.googleads.v15.enums.types import ( + feed_item_quality_disapproval_reason, +) +from google.ads.googleads.v15.enums.types import feed_item_status +from google.ads.googleads.v15.enums.types import feed_item_validation_status +from google.ads.googleads.v15.enums.types import ( + geo_targeting_restriction as gage_geo_targeting_restriction, +) +from google.ads.googleads.v15.enums.types import placeholder_type +from google.ads.googleads.v15.enums.types import policy_approval_status +from google.ads.googleads.v15.enums.types import policy_review_status +from google.ads.googleads.v15.errors.types import feed_item_validation_error + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "FeedItem", + "FeedItemAttributeValue", + "FeedItemPlaceholderPolicyInfo", + "FeedItemValidationError", + }, +) + + +class FeedItem(proto.Message): + r"""A feed item. + .. _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 feed item. Feed item + resource names have the form: + + ``customers/{customer_id}/feedItems/{feed_id}~{feed_item_id}`` + feed (str): + Immutable. The feed to which this feed item + belongs. + + This field is a member of `oneof`_ ``_feed``. + id (int): + Output only. The ID of this feed item. + + This field is a member of `oneof`_ ``_id``. + start_date_time (str): + Start time in which this feed item is + effective and can begin serving. The time is in + the customer's time zone. 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`_ ``_start_date_time``. + end_date_time (str): + End time in which this feed item is no longer + effective and will stop serving. The time is in + the customer's time zone. 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`_ ``_end_date_time``. + attribute_values (MutableSequence[google.ads.googleads.v15.resources.types.FeedItemAttributeValue]): + The feed item's attribute values. + geo_targeting_restriction (google.ads.googleads.v15.enums.types.GeoTargetingRestrictionEnum.GeoTargetingRestriction): + Geo targeting restriction specifies the type + of location that can be used for targeting. + url_custom_parameters (MutableSequence[google.ads.googleads.v15.common.types.CustomParameter]): + The list of mappings used to substitute custom parameter + tags in a ``tracking_url_template``, ``final_urls``, or + ``mobile_final_urls``. + status (google.ads.googleads.v15.enums.types.FeedItemStatusEnum.FeedItemStatus): + Output only. Status of the feed item. + This field is read-only. + policy_infos (MutableSequence[google.ads.googleads.v15.resources.types.FeedItemPlaceholderPolicyInfo]): + Output only. List of info about a feed item's + validation and approval state for active feed + mappings. There will be an entry in the list for + each type of feed mapping associated with the + feed, for example, a feed with a sitelink and a + call feed mapping would cause every feed item + associated with that feed to have an entry in + this list for both sitelink and call. This field + is read-only. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + feed: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + id: int = proto.Field( + proto.INT64, + number=12, + optional=True, + ) + start_date_time: str = proto.Field( + proto.STRING, + number=13, + optional=True, + ) + end_date_time: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + attribute_values: MutableSequence[ + "FeedItemAttributeValue" + ] = proto.RepeatedField( + proto.MESSAGE, + number=6, + message="FeedItemAttributeValue", + ) + geo_targeting_restriction: gage_geo_targeting_restriction.GeoTargetingRestrictionEnum.GeoTargetingRestriction = proto.Field( + proto.ENUM, + number=7, + enum=gage_geo_targeting_restriction.GeoTargetingRestrictionEnum.GeoTargetingRestriction, + ) + url_custom_parameters: MutableSequence[ + custom_parameter.CustomParameter + ] = proto.RepeatedField( + proto.MESSAGE, + number=8, + message=custom_parameter.CustomParameter, + ) + status: feed_item_status.FeedItemStatusEnum.FeedItemStatus = proto.Field( + proto.ENUM, + number=9, + enum=feed_item_status.FeedItemStatusEnum.FeedItemStatus, + ) + policy_infos: MutableSequence[ + "FeedItemPlaceholderPolicyInfo" + ] = proto.RepeatedField( + proto.MESSAGE, + number=10, + message="FeedItemPlaceholderPolicyInfo", + ) + + +class FeedItemAttributeValue(proto.Message): + r"""A feed item attribute value. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + feed_attribute_id (int): + Id of the feed attribute for which the value + is associated with. + + This field is a member of `oneof`_ ``_feed_attribute_id``. + integer_value (int): + Int64 value. Should be set if feed_attribute_id refers to a + feed attribute of type INT64. + + This field is a member of `oneof`_ ``_integer_value``. + boolean_value (bool): + Bool value. Should be set if feed_attribute_id refers to a + feed attribute of type BOOLEAN. + + This field is a member of `oneof`_ ``_boolean_value``. + string_value (str): + String value. Should be set if feed_attribute_id refers to a + feed attribute of type STRING, URL or DATE_TIME. For STRING + the maximum length is 1500 characters. For URL the maximum + length is 2076 characters. For DATE_TIME the string must be + in the format "YYYYMMDD HHMMSS". + + This field is a member of `oneof`_ ``_string_value``. + double_value (float): + Double value. Should be set if feed_attribute_id refers to a + feed attribute of type DOUBLE. + + This field is a member of `oneof`_ ``_double_value``. + price_value (google.ads.googleads.v15.common.types.Money): + Price value. Should be set if feed_attribute_id refers to a + feed attribute of type PRICE. + integer_values (MutableSequence[int]): + Repeated int64 value. Should be set if feed_attribute_id + refers to a feed attribute of type INT64_LIST. + boolean_values (MutableSequence[bool]): + Repeated bool value. Should be set if feed_attribute_id + refers to a feed attribute of type BOOLEAN_LIST. + string_values (MutableSequence[str]): + Repeated string value. Should be set if feed_attribute_id + refers to a feed attribute of type STRING_LIST, URL_LIST or + DATE_TIME_LIST. For STRING_LIST and URL_LIST the total size + of the list in bytes may not exceed 3000. For DATE_TIME_LIST + the number of elements may not exceed 200. + + For STRING_LIST the maximum length of each string element is + 1500 characters. For URL_LIST the maximum length is 2076 + characters. For DATE_TIME the format of the string must be + the same as start and end time for the feed item. + double_values (MutableSequence[float]): + Repeated double value. Should be set if feed_attribute_id + refers to a feed attribute of type DOUBLE_LIST. + """ + + feed_attribute_id: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + integer_value: int = proto.Field( + proto.INT64, + number=12, + optional=True, + ) + boolean_value: bool = proto.Field( + proto.BOOL, + number=13, + optional=True, + ) + string_value: str = proto.Field( + proto.STRING, + number=14, + optional=True, + ) + double_value: float = proto.Field( + proto.DOUBLE, + number=15, + optional=True, + ) + price_value: feed_common.Money = proto.Field( + proto.MESSAGE, + number=6, + message=feed_common.Money, + ) + integer_values: MutableSequence[int] = proto.RepeatedField( + proto.INT64, + number=16, + ) + boolean_values: MutableSequence[bool] = proto.RepeatedField( + proto.BOOL, + number=17, + ) + string_values: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=18, + ) + double_values: MutableSequence[float] = proto.RepeatedField( + proto.DOUBLE, + number=19, + ) + + +class FeedItemPlaceholderPolicyInfo(proto.Message): + r"""Policy, validation, and quality approval info for a feed item + for the specified placeholder type. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + placeholder_type_enum (google.ads.googleads.v15.enums.types.PlaceholderTypeEnum.PlaceholderType): + Output only. The placeholder type. + feed_mapping_resource_name (str): + Output only. The FeedMapping that contains + the placeholder type. + + This field is a member of `oneof`_ ``_feed_mapping_resource_name``. + review_status (google.ads.googleads.v15.enums.types.PolicyReviewStatusEnum.PolicyReviewStatus): + Output only. Where the placeholder type is in + the review process. + approval_status (google.ads.googleads.v15.enums.types.PolicyApprovalStatusEnum.PolicyApprovalStatus): + Output only. The overall approval status of + the placeholder type, calculated based on the + status of its individual policy topic entries. + policy_topic_entries (MutableSequence[google.ads.googleads.v15.common.types.PolicyTopicEntry]): + Output only. The list of policy findings for + the placeholder type. + validation_status (google.ads.googleads.v15.enums.types.FeedItemValidationStatusEnum.FeedItemValidationStatus): + Output only. The validation status of the + placeholder type. + validation_errors (MutableSequence[google.ads.googleads.v15.resources.types.FeedItemValidationError]): + Output only. List of placeholder type + validation errors. + quality_approval_status (google.ads.googleads.v15.enums.types.FeedItemQualityApprovalStatusEnum.FeedItemQualityApprovalStatus): + Output only. Placeholder type quality + evaluation approval status. + quality_disapproval_reasons (MutableSequence[google.ads.googleads.v15.enums.types.FeedItemQualityDisapprovalReasonEnum.FeedItemQualityDisapprovalReason]): + Output only. List of placeholder type quality + evaluation disapproval reasons. + """ + + placeholder_type_enum: placeholder_type.PlaceholderTypeEnum.PlaceholderType = proto.Field( + proto.ENUM, + number=10, + enum=placeholder_type.PlaceholderTypeEnum.PlaceholderType, + ) + feed_mapping_resource_name: str = proto.Field( + proto.STRING, + number=11, + optional=True, + ) + review_status: policy_review_status.PolicyReviewStatusEnum.PolicyReviewStatus = proto.Field( + proto.ENUM, + number=3, + enum=policy_review_status.PolicyReviewStatusEnum.PolicyReviewStatus, + ) + approval_status: policy_approval_status.PolicyApprovalStatusEnum.PolicyApprovalStatus = proto.Field( + proto.ENUM, + number=4, + enum=policy_approval_status.PolicyApprovalStatusEnum.PolicyApprovalStatus, + ) + policy_topic_entries: MutableSequence[ + policy.PolicyTopicEntry + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=policy.PolicyTopicEntry, + ) + validation_status: feed_item_validation_status.FeedItemValidationStatusEnum.FeedItemValidationStatus = proto.Field( + proto.ENUM, + number=6, + enum=feed_item_validation_status.FeedItemValidationStatusEnum.FeedItemValidationStatus, + ) + validation_errors: MutableSequence[ + "FeedItemValidationError" + ] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message="FeedItemValidationError", + ) + quality_approval_status: feed_item_quality_approval_status.FeedItemQualityApprovalStatusEnum.FeedItemQualityApprovalStatus = proto.Field( + proto.ENUM, + number=8, + enum=feed_item_quality_approval_status.FeedItemQualityApprovalStatusEnum.FeedItemQualityApprovalStatus, + ) + quality_disapproval_reasons: MutableSequence[ + feed_item_quality_disapproval_reason.FeedItemQualityDisapprovalReasonEnum.FeedItemQualityDisapprovalReason + ] = proto.RepeatedField( + proto.ENUM, + number=9, + enum=feed_item_quality_disapproval_reason.FeedItemQualityDisapprovalReasonEnum.FeedItemQualityDisapprovalReason, + ) + + +class FeedItemValidationError(proto.Message): + r"""Stores a validation error and the set of offending feed + attributes which together are responsible for causing a feed + item validation error. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + validation_error (google.ads.googleads.v15.errors.types.FeedItemValidationErrorEnum.FeedItemValidationError): + Output only. Error code indicating what + validation error was triggered. The description + of the error can be found in the 'description' + field. + description (str): + Output only. The description of the + validation error. + + This field is a member of `oneof`_ ``_description``. + feed_attribute_ids (MutableSequence[int]): + Output only. Set of feed attributes in the + feed item flagged during validation. If empty, + no specific feed attributes can be associated + with the error (for example, error across the + entire feed item). + extra_info (str): + Output only. Any extra information related to this error + which is not captured by validation_error and + feed_attribute_id (for example, placeholder field IDs when + feed_attribute_id is not mapped). Note that extra_info is + not localized. + + This field is a member of `oneof`_ ``_extra_info``. + """ + + validation_error: feed_item_validation_error.FeedItemValidationErrorEnum.FeedItemValidationError = proto.Field( + proto.ENUM, + number=1, + enum=feed_item_validation_error.FeedItemValidationErrorEnum.FeedItemValidationError, + ) + description: str = proto.Field( + proto.STRING, + number=6, + optional=True, + ) + feed_attribute_ids: MutableSequence[int] = proto.RepeatedField( + proto.INT64, + number=7, + ) + extra_info: str = proto.Field( + proto.STRING, + number=8, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/feed_item_set.py b/google/ads/googleads/v15/resources/types/feed_item_set.py new file mode 100644 index 000000000..5a6bcbeae --- /dev/null +++ b/google/ads/googleads/v15/resources/types/feed_item_set.py @@ -0,0 +1,117 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import ( + feed_item_set_filter_type_infos, +) +from google.ads.googleads.v15.enums.types import feed_item_set_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "FeedItemSet", + }, +) + + +class FeedItemSet(proto.Message): + r"""Represents a set of feed items. The set can be used and + shared among certain feed item features. For instance, the set + can be referenced within the matching functions of CustomerFeed, + CampaignFeed, and AdGroupFeed. + + 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 feed item set. Feed item + set resource names have the form: + ``customers/{customer_id}/feedItemSets/{feed_id}~{feed_item_set_id}`` + feed (str): + Immutable. The resource name of the feed + containing the feed items in the set. Immutable. + Required. + feed_item_set_id (int): + Output only. ID of the set. + display_name (str): + Name of the set. Must be unique within the + account. + status (google.ads.googleads.v15.enums.types.FeedItemSetStatusEnum.FeedItemSetStatus): + Output only. Status of the feed item set. + This field is read-only. + dynamic_location_set_filter (google.ads.googleads.v15.common.types.DynamicLocationSetFilter): + Filter for dynamic location set. + It is only used for sets of locations. + + This field is a member of `oneof`_ ``dynamic_set_filter``. + dynamic_affiliate_location_set_filter (google.ads.googleads.v15.common.types.DynamicAffiliateLocationSetFilter): + Filter for dynamic affiliate location set. + This field doesn't apply generally to feed item + sets. It is only used for sets of affiliate + locations. + + This field is a member of `oneof`_ ``dynamic_set_filter``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + feed: str = proto.Field( + proto.STRING, + number=2, + ) + feed_item_set_id: int = proto.Field( + proto.INT64, + number=3, + ) + display_name: str = proto.Field( + proto.STRING, + number=4, + ) + status: feed_item_set_status.FeedItemSetStatusEnum.FeedItemSetStatus = ( + proto.Field( + proto.ENUM, + number=8, + enum=feed_item_set_status.FeedItemSetStatusEnum.FeedItemSetStatus, + ) + ) + dynamic_location_set_filter: feed_item_set_filter_type_infos.DynamicLocationSetFilter = proto.Field( + proto.MESSAGE, + number=5, + oneof="dynamic_set_filter", + message=feed_item_set_filter_type_infos.DynamicLocationSetFilter, + ) + dynamic_affiliate_location_set_filter: feed_item_set_filter_type_infos.DynamicAffiliateLocationSetFilter = proto.Field( + proto.MESSAGE, + number=6, + oneof="dynamic_set_filter", + message=feed_item_set_filter_type_infos.DynamicAffiliateLocationSetFilter, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/feed_item_set_link.py b/google/ads/googleads/v15/resources/types/feed_item_set_link.py new file mode 100644 index 000000000..c6bac0529 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/feed_item_set_link.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "FeedItemSetLink", + }, +) + + +class FeedItemSetLink(proto.Message): + r"""Represents a link between a FeedItem and a FeedItemSet. + Attributes: + resource_name (str): + Immutable. The resource name of the feed item set link. Feed + item set link resource names have the form: + ``customers/{customer_id}/feedItemSetLinks/{feed_id}~{feed_item_set_id}~{feed_item_id}`` + feed_item (str): + Immutable. The linked FeedItem. + feed_item_set (str): + Immutable. The linked FeedItemSet. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + feed_item: str = proto.Field( + proto.STRING, + number=2, + ) + feed_item_set: str = proto.Field( + proto.STRING, + number=3, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/feed_item_target.py b/google/ads/googleads/v15/resources/types/feed_item_target.py new file mode 100644 index 000000000..b766d954d --- /dev/null +++ b/google/ads/googleads/v15/resources/types/feed_item_target.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import criteria +from google.ads.googleads.v15.enums.types import feed_item_target_device +from google.ads.googleads.v15.enums.types import feed_item_target_status +from google.ads.googleads.v15.enums.types import ( + feed_item_target_type as gage_feed_item_target_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "FeedItemTarget", + }, +) + + +class FeedItemTarget(proto.Message): + r"""A feed item target. + 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 feed item target. Feed + item target resource names have the form: + ``customers/{customer_id}/feedItemTargets/{feed_id}~{feed_item_id}~{feed_item_target_type}~{feed_item_target_id}`` + feed_item (str): + Immutable. The feed item to which this feed + item target belongs. + + This field is a member of `oneof`_ ``_feed_item``. + feed_item_target_type (google.ads.googleads.v15.enums.types.FeedItemTargetTypeEnum.FeedItemTargetType): + Output only. The target type of this feed + item target. This field is read-only. + feed_item_target_id (int): + Output only. The ID of the targeted resource. + This field is read-only. + + This field is a member of `oneof`_ ``_feed_item_target_id``. + status (google.ads.googleads.v15.enums.types.FeedItemTargetStatusEnum.FeedItemTargetStatus): + Output only. Status of the feed item target. + This field is read-only. + campaign (str): + Immutable. The targeted campaign. + + This field is a member of `oneof`_ ``target``. + ad_group (str): + Immutable. The targeted ad group. + + This field is a member of `oneof`_ ``target``. + keyword (google.ads.googleads.v15.common.types.KeywordInfo): + Immutable. The targeted keyword. + + This field is a member of `oneof`_ ``target``. + geo_target_constant (str): + Immutable. The targeted geo target constant + resource name. + + This field is a member of `oneof`_ ``target``. + device (google.ads.googleads.v15.enums.types.FeedItemTargetDeviceEnum.FeedItemTargetDevice): + Immutable. The targeted device. + + This field is a member of `oneof`_ ``target``. + ad_schedule (google.ads.googleads.v15.common.types.AdScheduleInfo): + Immutable. The targeted schedule. + + This field is a member of `oneof`_ ``target``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + feed_item: str = proto.Field( + proto.STRING, + number=12, + optional=True, + ) + feed_item_target_type: gage_feed_item_target_type.FeedItemTargetTypeEnum.FeedItemTargetType = proto.Field( + proto.ENUM, + number=3, + enum=gage_feed_item_target_type.FeedItemTargetTypeEnum.FeedItemTargetType, + ) + feed_item_target_id: int = proto.Field( + proto.INT64, + number=13, + optional=True, + ) + status: feed_item_target_status.FeedItemTargetStatusEnum.FeedItemTargetStatus = proto.Field( + proto.ENUM, + number=11, + enum=feed_item_target_status.FeedItemTargetStatusEnum.FeedItemTargetStatus, + ) + campaign: str = proto.Field( + proto.STRING, + number=14, + oneof="target", + ) + ad_group: str = proto.Field( + proto.STRING, + number=15, + oneof="target", + ) + keyword: criteria.KeywordInfo = proto.Field( + proto.MESSAGE, + number=7, + oneof="target", + message=criteria.KeywordInfo, + ) + geo_target_constant: str = proto.Field( + proto.STRING, + number=16, + oneof="target", + ) + device: feed_item_target_device.FeedItemTargetDeviceEnum.FeedItemTargetDevice = proto.Field( + proto.ENUM, + number=9, + oneof="target", + enum=feed_item_target_device.FeedItemTargetDeviceEnum.FeedItemTargetDevice, + ) + ad_schedule: criteria.AdScheduleInfo = proto.Field( + proto.MESSAGE, + number=10, + oneof="target", + message=criteria.AdScheduleInfo, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/feed_mapping.py b/google/ads/googleads/v15/resources/types/feed_mapping.py new file mode 100644 index 000000000..726961860 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/feed_mapping.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ad_customizer_placeholder_field +from google.ads.googleads.v15.enums.types import ( + affiliate_location_placeholder_field, +) +from google.ads.googleads.v15.enums.types import app_placeholder_field +from google.ads.googleads.v15.enums.types import call_placeholder_field +from google.ads.googleads.v15.enums.types import callout_placeholder_field +from google.ads.googleads.v15.enums.types import custom_placeholder_field +from google.ads.googleads.v15.enums.types import dsa_page_feed_criterion_field +from google.ads.googleads.v15.enums.types import education_placeholder_field +from google.ads.googleads.v15.enums.types import feed_mapping_criterion_type +from google.ads.googleads.v15.enums.types import feed_mapping_status +from google.ads.googleads.v15.enums.types import flight_placeholder_field +from google.ads.googleads.v15.enums.types import hotel_placeholder_field +from google.ads.googleads.v15.enums.types import image_placeholder_field +from google.ads.googleads.v15.enums.types import job_placeholder_field +from google.ads.googleads.v15.enums.types import local_placeholder_field +from google.ads.googleads.v15.enums.types import ( + location_extension_targeting_criterion_field, +) +from google.ads.googleads.v15.enums.types import location_placeholder_field +from google.ads.googleads.v15.enums.types import message_placeholder_field +from google.ads.googleads.v15.enums.types import ( + placeholder_type as gage_placeholder_type, +) +from google.ads.googleads.v15.enums.types import price_placeholder_field +from google.ads.googleads.v15.enums.types import promotion_placeholder_field +from google.ads.googleads.v15.enums.types import real_estate_placeholder_field +from google.ads.googleads.v15.enums.types import sitelink_placeholder_field +from google.ads.googleads.v15.enums.types import ( + structured_snippet_placeholder_field, +) +from google.ads.googleads.v15.enums.types import travel_placeholder_field + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "FeedMapping", + "AttributeFieldMapping", + }, +) + + +class FeedMapping(proto.Message): + r"""A feed mapping. + 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 feed mapping. Feed + mapping resource names have the form: + + ``customers/{customer_id}/feedMappings/{feed_id}~{feed_mapping_id}`` + feed (str): + Immutable. The feed of this feed mapping. + + This field is a member of `oneof`_ ``_feed``. + attribute_field_mappings (MutableSequence[google.ads.googleads.v15.resources.types.AttributeFieldMapping]): + Immutable. Feed attributes to field mappings. + These mappings are a one-to-many relationship + meaning that 1 feed attribute can be used to + populate multiple placeholder fields, but 1 + placeholder field can only draw data from 1 feed + attribute. Ad Customizer is an exception, 1 + placeholder field can be mapped to multiple feed + attributes. Required. + status (google.ads.googleads.v15.enums.types.FeedMappingStatusEnum.FeedMappingStatus): + Output only. Status of the feed mapping. + This field is read-only. + placeholder_type (google.ads.googleads.v15.enums.types.PlaceholderTypeEnum.PlaceholderType): + Immutable. The placeholder type of this + mapping (for example, if the mapping maps feed + attributes to placeholder fields). + + This field is a member of `oneof`_ ``target``. + criterion_type (google.ads.googleads.v15.enums.types.FeedMappingCriterionTypeEnum.FeedMappingCriterionType): + Immutable. The criterion type of this mapping + (for example, if the mapping maps feed + attributes to criterion fields). + + This field is a member of `oneof`_ ``target``. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + feed: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) + attribute_field_mappings: MutableSequence[ + "AttributeFieldMapping" + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="AttributeFieldMapping", + ) + status: feed_mapping_status.FeedMappingStatusEnum.FeedMappingStatus = ( + proto.Field( + proto.ENUM, + number=6, + enum=feed_mapping_status.FeedMappingStatusEnum.FeedMappingStatus, + ) + ) + placeholder_type: gage_placeholder_type.PlaceholderTypeEnum.PlaceholderType = proto.Field( + proto.ENUM, + number=3, + oneof="target", + enum=gage_placeholder_type.PlaceholderTypeEnum.PlaceholderType, + ) + criterion_type: feed_mapping_criterion_type.FeedMappingCriterionTypeEnum.FeedMappingCriterionType = proto.Field( + proto.ENUM, + number=4, + oneof="target", + enum=feed_mapping_criterion_type.FeedMappingCriterionTypeEnum.FeedMappingCriterionType, + ) + + +class AttributeFieldMapping(proto.Message): + r"""Maps from feed attribute id to a placeholder or criterion + field id. + + 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: + feed_attribute_id (int): + Immutable. Feed attribute from which to map. + + This field is a member of `oneof`_ ``_feed_attribute_id``. + field_id (int): + Output only. The placeholder field ID. If a + placeholder field enum is not published in the + current API version, then this field will be + populated and the field oneof will be empty. + This field is read-only. + + This field is a member of `oneof`_ ``_field_id``. + sitelink_field (google.ads.googleads.v15.enums.types.SitelinkPlaceholderFieldEnum.SitelinkPlaceholderField): + Immutable. Sitelink Placeholder Fields. + + This field is a member of `oneof`_ ``field``. + call_field (google.ads.googleads.v15.enums.types.CallPlaceholderFieldEnum.CallPlaceholderField): + Immutable. Call Placeholder Fields. + + This field is a member of `oneof`_ ``field``. + app_field (google.ads.googleads.v15.enums.types.AppPlaceholderFieldEnum.AppPlaceholderField): + Immutable. App Placeholder Fields. + + This field is a member of `oneof`_ ``field``. + location_field (google.ads.googleads.v15.enums.types.LocationPlaceholderFieldEnum.LocationPlaceholderField): + Output only. Location Placeholder Fields. + This field is read-only. + + This field is a member of `oneof`_ ``field``. + affiliate_location_field (google.ads.googleads.v15.enums.types.AffiliateLocationPlaceholderFieldEnum.AffiliateLocationPlaceholderField): + Output only. Affiliate Location Placeholder + Fields. This field is read-only. + + This field is a member of `oneof`_ ``field``. + callout_field (google.ads.googleads.v15.enums.types.CalloutPlaceholderFieldEnum.CalloutPlaceholderField): + Immutable. Callout Placeholder Fields. + + This field is a member of `oneof`_ ``field``. + structured_snippet_field (google.ads.googleads.v15.enums.types.StructuredSnippetPlaceholderFieldEnum.StructuredSnippetPlaceholderField): + Immutable. Structured Snippet Placeholder + Fields. + + This field is a member of `oneof`_ ``field``. + message_field (google.ads.googleads.v15.enums.types.MessagePlaceholderFieldEnum.MessagePlaceholderField): + Immutable. Message Placeholder Fields. + + This field is a member of `oneof`_ ``field``. + price_field (google.ads.googleads.v15.enums.types.PricePlaceholderFieldEnum.PricePlaceholderField): + Immutable. Price Placeholder Fields. + + This field is a member of `oneof`_ ``field``. + promotion_field (google.ads.googleads.v15.enums.types.PromotionPlaceholderFieldEnum.PromotionPlaceholderField): + Immutable. Promotion Placeholder Fields. + + This field is a member of `oneof`_ ``field``. + ad_customizer_field (google.ads.googleads.v15.enums.types.AdCustomizerPlaceholderFieldEnum.AdCustomizerPlaceholderField): + Immutable. Ad Customizer Placeholder Fields + + This field is a member of `oneof`_ ``field``. + dsa_page_feed_field (google.ads.googleads.v15.enums.types.DsaPageFeedCriterionFieldEnum.DsaPageFeedCriterionField): + Immutable. Dynamic Search Ad Page Feed + Fields. + + This field is a member of `oneof`_ ``field``. + location_extension_targeting_field (google.ads.googleads.v15.enums.types.LocationExtensionTargetingCriterionFieldEnum.LocationExtensionTargetingCriterionField): + Immutable. Location Target Fields. + + This field is a member of `oneof`_ ``field``. + education_field (google.ads.googleads.v15.enums.types.EducationPlaceholderFieldEnum.EducationPlaceholderField): + Immutable. Education Placeholder Fields + + This field is a member of `oneof`_ ``field``. + flight_field (google.ads.googleads.v15.enums.types.FlightPlaceholderFieldEnum.FlightPlaceholderField): + Immutable. Flight Placeholder Fields + + This field is a member of `oneof`_ ``field``. + custom_field (google.ads.googleads.v15.enums.types.CustomPlaceholderFieldEnum.CustomPlaceholderField): + Immutable. Custom Placeholder Fields + + This field is a member of `oneof`_ ``field``. + hotel_field (google.ads.googleads.v15.enums.types.HotelPlaceholderFieldEnum.HotelPlaceholderField): + Immutable. Hotel Placeholder Fields + + This field is a member of `oneof`_ ``field``. + real_estate_field (google.ads.googleads.v15.enums.types.RealEstatePlaceholderFieldEnum.RealEstatePlaceholderField): + Immutable. Real Estate Placeholder Fields + + This field is a member of `oneof`_ ``field``. + travel_field (google.ads.googleads.v15.enums.types.TravelPlaceholderFieldEnum.TravelPlaceholderField): + Immutable. Travel Placeholder Fields + + This field is a member of `oneof`_ ``field``. + local_field (google.ads.googleads.v15.enums.types.LocalPlaceholderFieldEnum.LocalPlaceholderField): + Immutable. Local Placeholder Fields + + This field is a member of `oneof`_ ``field``. + job_field (google.ads.googleads.v15.enums.types.JobPlaceholderFieldEnum.JobPlaceholderField): + Immutable. Job Placeholder Fields + + This field is a member of `oneof`_ ``field``. + image_field (google.ads.googleads.v15.enums.types.ImagePlaceholderFieldEnum.ImagePlaceholderField): + Immutable. Image Placeholder Fields + + This field is a member of `oneof`_ ``field``. + """ + + feed_attribute_id: int = proto.Field( + proto.INT64, + number=24, + optional=True, + ) + field_id: int = proto.Field( + proto.INT64, + number=25, + optional=True, + ) + sitelink_field: sitelink_placeholder_field.SitelinkPlaceholderFieldEnum.SitelinkPlaceholderField = proto.Field( + proto.ENUM, + number=3, + oneof="field", + enum=sitelink_placeholder_field.SitelinkPlaceholderFieldEnum.SitelinkPlaceholderField, + ) + call_field: call_placeholder_field.CallPlaceholderFieldEnum.CallPlaceholderField = proto.Field( + proto.ENUM, + number=4, + oneof="field", + enum=call_placeholder_field.CallPlaceholderFieldEnum.CallPlaceholderField, + ) + app_field: app_placeholder_field.AppPlaceholderFieldEnum.AppPlaceholderField = proto.Field( + proto.ENUM, + number=5, + oneof="field", + enum=app_placeholder_field.AppPlaceholderFieldEnum.AppPlaceholderField, + ) + location_field: location_placeholder_field.LocationPlaceholderFieldEnum.LocationPlaceholderField = proto.Field( + proto.ENUM, + number=6, + oneof="field", + enum=location_placeholder_field.LocationPlaceholderFieldEnum.LocationPlaceholderField, + ) + affiliate_location_field: affiliate_location_placeholder_field.AffiliateLocationPlaceholderFieldEnum.AffiliateLocationPlaceholderField = proto.Field( + proto.ENUM, + number=7, + oneof="field", + enum=affiliate_location_placeholder_field.AffiliateLocationPlaceholderFieldEnum.AffiliateLocationPlaceholderField, + ) + callout_field: callout_placeholder_field.CalloutPlaceholderFieldEnum.CalloutPlaceholderField = proto.Field( + proto.ENUM, + number=8, + oneof="field", + enum=callout_placeholder_field.CalloutPlaceholderFieldEnum.CalloutPlaceholderField, + ) + structured_snippet_field: structured_snippet_placeholder_field.StructuredSnippetPlaceholderFieldEnum.StructuredSnippetPlaceholderField = proto.Field( + proto.ENUM, + number=9, + oneof="field", + enum=structured_snippet_placeholder_field.StructuredSnippetPlaceholderFieldEnum.StructuredSnippetPlaceholderField, + ) + message_field: message_placeholder_field.MessagePlaceholderFieldEnum.MessagePlaceholderField = proto.Field( + proto.ENUM, + number=10, + oneof="field", + enum=message_placeholder_field.MessagePlaceholderFieldEnum.MessagePlaceholderField, + ) + price_field: price_placeholder_field.PricePlaceholderFieldEnum.PricePlaceholderField = proto.Field( + proto.ENUM, + number=11, + oneof="field", + enum=price_placeholder_field.PricePlaceholderFieldEnum.PricePlaceholderField, + ) + promotion_field: promotion_placeholder_field.PromotionPlaceholderFieldEnum.PromotionPlaceholderField = proto.Field( + proto.ENUM, + number=12, + oneof="field", + enum=promotion_placeholder_field.PromotionPlaceholderFieldEnum.PromotionPlaceholderField, + ) + ad_customizer_field: ad_customizer_placeholder_field.AdCustomizerPlaceholderFieldEnum.AdCustomizerPlaceholderField = proto.Field( + proto.ENUM, + number=13, + oneof="field", + enum=ad_customizer_placeholder_field.AdCustomizerPlaceholderFieldEnum.AdCustomizerPlaceholderField, + ) + dsa_page_feed_field: dsa_page_feed_criterion_field.DsaPageFeedCriterionFieldEnum.DsaPageFeedCriterionField = proto.Field( + proto.ENUM, + number=14, + oneof="field", + enum=dsa_page_feed_criterion_field.DsaPageFeedCriterionFieldEnum.DsaPageFeedCriterionField, + ) + location_extension_targeting_field: location_extension_targeting_criterion_field.LocationExtensionTargetingCriterionFieldEnum.LocationExtensionTargetingCriterionField = proto.Field( + proto.ENUM, + number=15, + oneof="field", + enum=location_extension_targeting_criterion_field.LocationExtensionTargetingCriterionFieldEnum.LocationExtensionTargetingCriterionField, + ) + education_field: education_placeholder_field.EducationPlaceholderFieldEnum.EducationPlaceholderField = proto.Field( + proto.ENUM, + number=16, + oneof="field", + enum=education_placeholder_field.EducationPlaceholderFieldEnum.EducationPlaceholderField, + ) + flight_field: flight_placeholder_field.FlightPlaceholderFieldEnum.FlightPlaceholderField = proto.Field( + proto.ENUM, + number=17, + oneof="field", + enum=flight_placeholder_field.FlightPlaceholderFieldEnum.FlightPlaceholderField, + ) + custom_field: custom_placeholder_field.CustomPlaceholderFieldEnum.CustomPlaceholderField = proto.Field( + proto.ENUM, + number=18, + oneof="field", + enum=custom_placeholder_field.CustomPlaceholderFieldEnum.CustomPlaceholderField, + ) + hotel_field: hotel_placeholder_field.HotelPlaceholderFieldEnum.HotelPlaceholderField = proto.Field( + proto.ENUM, + number=19, + oneof="field", + enum=hotel_placeholder_field.HotelPlaceholderFieldEnum.HotelPlaceholderField, + ) + real_estate_field: real_estate_placeholder_field.RealEstatePlaceholderFieldEnum.RealEstatePlaceholderField = proto.Field( + proto.ENUM, + number=20, + oneof="field", + enum=real_estate_placeholder_field.RealEstatePlaceholderFieldEnum.RealEstatePlaceholderField, + ) + travel_field: travel_placeholder_field.TravelPlaceholderFieldEnum.TravelPlaceholderField = proto.Field( + proto.ENUM, + number=21, + oneof="field", + enum=travel_placeholder_field.TravelPlaceholderFieldEnum.TravelPlaceholderField, + ) + local_field: local_placeholder_field.LocalPlaceholderFieldEnum.LocalPlaceholderField = proto.Field( + proto.ENUM, + number=22, + oneof="field", + enum=local_placeholder_field.LocalPlaceholderFieldEnum.LocalPlaceholderField, + ) + job_field: job_placeholder_field.JobPlaceholderFieldEnum.JobPlaceholderField = proto.Field( + proto.ENUM, + number=23, + oneof="field", + enum=job_placeholder_field.JobPlaceholderFieldEnum.JobPlaceholderField, + ) + image_field: image_placeholder_field.ImagePlaceholderFieldEnum.ImagePlaceholderField = proto.Field( + proto.ENUM, + number=26, + oneof="field", + enum=image_placeholder_field.ImagePlaceholderFieldEnum.ImagePlaceholderField, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/feed_placeholder_view.py b/google/ads/googleads/v15/resources/types/feed_placeholder_view.py new file mode 100644 index 000000000..e4e0b32c8 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/feed_placeholder_view.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + placeholder_type as gage_placeholder_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "FeedPlaceholderView", + }, +) + + +class FeedPlaceholderView(proto.Message): + r"""A feed placeholder view. + Attributes: + resource_name (str): + Output only. The resource name of the feed placeholder view. + Feed placeholder view resource names have the form: + + ``customers/{customer_id}/feedPlaceholderViews/{placeholder_type}`` + placeholder_type (google.ads.googleads.v15.enums.types.PlaceholderTypeEnum.PlaceholderType): + Output only. The placeholder type of the feed + placeholder view. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + placeholder_type: gage_placeholder_type.PlaceholderTypeEnum.PlaceholderType = proto.Field( + proto.ENUM, + number=2, + enum=gage_placeholder_type.PlaceholderTypeEnum.PlaceholderType, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/gender_view.py b/google/ads/googleads/v15/resources/types/gender_view.py new file mode 100644 index 000000000..e05115c9f --- /dev/null +++ b/google/ads/googleads/v15/resources/types/gender_view.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "GenderView", + }, +) + + +class GenderView(proto.Message): + r"""A gender view. + 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/v15/resources/types/geo_target_constant.py b/google/ads/googleads/v15/resources/types/geo_target_constant.py new file mode 100644 index 000000000..3495f8684 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/geo_target_constant.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import geo_target_constant_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/geographic_view.py b/google/ads/googleads/v15/resources/types/geographic_view.py new file mode 100644 index 000000000..2851aa52c --- /dev/null +++ b/google/ads/googleads/v15/resources/types/geographic_view.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import geo_targeting_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/google_ads_field.py b/google/ads/googleads/v15/resources/types/google_ads_field.py new file mode 100644 index 000000000..f21dbbc90 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/google_ads_field.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import google_ads_field_category +from google.ads.googleads.v15.enums.types import google_ads_field_data_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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/v15/resources/types/group_placement_view.py b/google/ads/googleads/v15/resources/types/group_placement_view.py new file mode 100644 index 000000000..7b3340911 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/group_placement_view.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + placement_type as gage_placement_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/hotel_group_view.py b/google/ads/googleads/v15/resources/types/hotel_group_view.py new file mode 100644 index 000000000..2ee643791 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/hotel_group_view.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/hotel_performance_view.py b/google/ads/googleads/v15/resources/types/hotel_performance_view.py new file mode 100644 index 000000000..ab70fd9d8 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/hotel_performance_view.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/hotel_reconciliation.py b/google/ads/googleads/v15/resources/types/hotel_reconciliation.py new file mode 100644 index 000000000..62a6316fb --- /dev/null +++ b/google/ads/googleads/v15/resources/types/hotel_reconciliation.py @@ -0,0 +1,152 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import hotel_reconciliation_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/income_range_view.py b/google/ads/googleads/v15/resources/types/income_range_view.py new file mode 100644 index 000000000..bec2bb6d1 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/income_range_view.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/invoice.py b/google/ads/googleads/v15/resources/types/invoice.py new file mode 100644 index 000000000..ef78bbe0b --- /dev/null +++ b/google/ads/googleads/v15/resources/types/invoice.py @@ -0,0 +1,766 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import dates +from google.ads.googleads.v15.enums.types import invoice_type +from google.ads.googleads.v15.enums.types import month_of_year + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.resources.types.Invoice.AccountBudgetSummary]): + Output only. The list of summarized account + budget information associated with this invoice. + account_summaries (MutableSequence[google.ads.googleads.v15.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``. + """ + + 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, + ) + + 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.v15.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.v15.resources.types.Invoice.InvalidActivitySummary]): + Output only. The list of summarized invalid + activity credits with original linkages. + """ + + 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", + ) + + 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.v15.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, + ) + + 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/v15/resources/types/keyword_plan.py b/google/ads/googleads/v15/resources/types/keyword_plan.py new file mode 100644 index 000000000..730f0c259 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/keyword_plan.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import dates +from google.ads.googleads.v15.enums.types import keyword_plan_forecast_interval + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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/v15/resources/types/keyword_plan_ad_group.py b/google/ads/googleads/v15/resources/types/keyword_plan_ad_group.py new file mode 100644 index 000000000..a0bb8fac2 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/keyword_plan_ad_group.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/keyword_plan_ad_group_keyword.py b/google/ads/googleads/v15/resources/types/keyword_plan_ad_group_keyword.py new file mode 100644 index 000000000..0814432af --- /dev/null +++ b/google/ads/googleads/v15/resources/types/keyword_plan_ad_group_keyword.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import keyword_match_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/keyword_plan_campaign.py b/google/ads/googleads/v15/resources/types/keyword_plan_campaign.py new file mode 100644 index 000000000..35a7ae929 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/keyword_plan_campaign.py @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + keyword_plan_network as gage_keyword_plan_network, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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/v15/resources/types/keyword_plan_campaign_keyword.py b/google/ads/googleads/v15/resources/types/keyword_plan_campaign_keyword.py new file mode 100644 index 000000000..d5ca59a9b --- /dev/null +++ b/google/ads/googleads/v15/resources/types/keyword_plan_campaign_keyword.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import keyword_match_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/keyword_theme_constant.py b/google/ads/googleads/v15/resources/types/keyword_theme_constant.py new file mode 100644 index 000000000..464da2972 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/keyword_theme_constant.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/keyword_view.py b/google/ads/googleads/v15/resources/types/keyword_view.py new file mode 100644 index 000000000..a91b1e31d --- /dev/null +++ b/google/ads/googleads/v15/resources/types/keyword_view.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/label.py b/google/ads/googleads/v15/resources/types/label.py new file mode 100644 index 000000000..c1bc71e6e --- /dev/null +++ b/google/ads/googleads/v15/resources/types/label.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import text_label as gagc_text_label +from google.ads.googleads.v15.enums.types import label_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.LabelStatusEnum.LabelStatus): + Output only. Status of the label. Read only. + text_label (google.ads.googleads.v15.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/v15/resources/types/landing_page_view.py b/google/ads/googleads/v15/resources/types/landing_page_view.py new file mode 100644 index 000000000..7e271fc10 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/landing_page_view.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/language_constant.py b/google/ads/googleads/v15/resources/types/language_constant.py new file mode 100644 index 000000000..e9d9860b4 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/language_constant.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/lead_form_submission_data.py b/google/ads/googleads/v15/resources/types/lead_form_submission_data.py new file mode 100644 index 000000000..de4bef0b9 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/lead_form_submission_data.py @@ -0,0 +1,164 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import lead_form_field_user_input_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.resources.types.LeadFormSubmissionField]): + Output only. Submission data associated with + a lead form. + custom_lead_form_submission_fields (MutableSequence[google.ads.googleads.v15.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.v15.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/v15/resources/types/life_event.py b/google/ads/googleads/v15/resources/types/life_event.py new file mode 100644 index 000000000..b8da8535b --- /dev/null +++ b/google/ads/googleads/v15/resources/types/life_event.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import ( + criterion_category_availability, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/local_services_lead.py b/google/ads/googleads/v15/resources/types/local_services_lead.py new file mode 100644 index 000000000..a30d392a7 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/local_services_lead.py @@ -0,0 +1,196 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import local_services_lead_status +from google.ads.googleads.v15.enums.types import local_services_lead_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "LocalServicesLead", + "ContactDetails", + "Note", + }, +) + + +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): + Output only. 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.v15.resources.types.ContactDetails): + Output only. Lead's contact details. + lead_type (google.ads.googleads.v15.enums.types.LocalServicesLeadTypeEnum.LeadType): + Output only. Type of Local Services lead: + phone, message, booking, etc. + lead_status (google.ads.googleads.v15.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.v15.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. + """ + + 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, + ) + + +class ContactDetails(proto.Message): + r"""Fields containing consumer contact details. + Attributes: + phone_number (str): + Output only. Consumer phone number in E164 + format. + 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/local_services_lead_conversation.py b/google/ads/googleads/v15/resources/types/local_services_lead_conversation.py new file mode 100644 index 000000000..5ace43d1c --- /dev/null +++ b/google/ads/googleads/v15/resources/types/local_services_lead_conversation.py @@ -0,0 +1,159 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + local_services_conversation_type, +) +from google.ads.googleads.v15.enums.types import local_services_participant_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.LocalServicesLeadConversationTypeEnum.ConversationType): + Output only. Type of GLS lead conversation, EMAIL, MESSAGE, + PHONE_CALL, SMS, etc. + participant_type (google.ads.googleads.v15.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.v15.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.v15.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. + """ + + text: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/local_services_verification_artifact.py b/google/ads/googleads/v15/resources/types/local_services_verification_artifact.py new file mode 100644 index 000000000..1a23c5e12 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/local_services_verification_artifact.py @@ -0,0 +1,291 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import local_services +from google.ads.googleads.v15.enums.types import ( + local_services_insurance_rejection_reason, +) +from google.ads.googleads.v15.enums.types import ( + local_services_license_rejection_reason, +) +from google.ads.googleads.v15.enums.types import ( + local_services_verification_artifact_status, +) +from google.ads.googleads.v15.enums.types import ( + local_services_verification_artifact_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "LocalServicesVerificationArtifact", + "BackgroundCheckVerificationArtifact", + "InsuranceVerificationArtifact", + "LicenseVerificationArtifact", + }, +) + + +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.v15.enums.types.LocalServicesVerificationArtifactStatusEnum.LocalServicesVerificationArtifactStatus): + Output only. The status of the verification + artifact. + artifact_type (google.ads.googleads.v15.enums.types.LocalServicesVerificationArtifactTypeEnum.LocalServicesVerificationArtifactType): + Output only. The type of the verification + artifact. + background_check_verification_artifact (google.ads.googleads.v15.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.v15.resources.types.InsuranceVerificationArtifact): + Output only. An insurance verification + artifact. + + This field is a member of `oneof`_ ``artifact_data``. + license_verification_artifact (google.ads.googleads.v15.resources.types.LicenseVerificationArtifact): + Output only. A license 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", + ) + + +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.v15.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.v15.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``. + """ + + 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, + ) + + +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.v15.enums.types.LocalServicesLicenseRejectionReasonEnum.LocalServicesLicenseRejectionReason): + Output only. License rejection reason. + + This field is a member of `oneof`_ ``_rejection_reason``. + license_document_readonly (google.ads.googleads.v15.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``. + """ + + 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, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/location_view.py b/google/ads/googleads/v15/resources/types/location_view.py new file mode 100644 index 000000000..ceb93c099 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/location_view.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "LocationView", + }, +) + + +class LocationView(proto.Message): + r"""A location view summarizes the performance of campaigns by + Location criteria. + + 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/v15/resources/types/managed_placement_view.py b/google/ads/googleads/v15/resources/types/managed_placement_view.py new file mode 100644 index 000000000..d55b406bc --- /dev/null +++ b/google/ads/googleads/v15/resources/types/managed_placement_view.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/media_file.py b/google/ads/googleads/v15/resources/types/media_file.py new file mode 100644 index 000000000..921c3b1f2 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/media_file.py @@ -0,0 +1,302 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import media_type +from google.ads.googleads.v15.enums.types import mime_type as gage_mime_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.MediaTypeEnum.MediaType): + Immutable. Type of the media file. + mime_type (google.ads.googleads.v15.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.v15.resources.types.MediaImage): + Immutable. Encapsulates an Image. + + This field is a member of `oneof`_ ``mediatype``. + media_bundle (google.ads.googleads.v15.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.v15.resources.types.MediaAudio): + Output only. Encapsulates an Audio. + + This field is a member of `oneof`_ ``mediatype``. + video (google.ads.googleads.v15.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/v15/resources/types/mobile_app_category_constant.py b/google/ads/googleads/v15/resources/types/mobile_app_category_constant.py new file mode 100644 index 000000000..8d58a7032 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/mobile_app_category_constant.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/mobile_device_constant.py b/google/ads/googleads/v15/resources/types/mobile_device_constant.py new file mode 100644 index 000000000..f35eba180 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/mobile_device_constant.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import mobile_device_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/offline_conversion_upload_client_summary.py b/google/ads/googleads/v15/resources/types/offline_conversion_upload_client_summary.py new file mode 100644 index 000000000..89266f667 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/offline_conversion_upload_client_summary.py @@ -0,0 +1,342 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + offline_conversion_diagnostic_status_enum, +) +from google.ads.googleads.v15.enums.types import ( + offline_event_upload_client_enum, +) +from google.ads.googleads.v15.errors.types import ( + collection_size_error as gage_collection_size_error, +) +from google.ads.googleads.v15.errors.types import ( + conversion_adjustment_upload_error as gage_conversion_adjustment_upload_error, +) +from google.ads.googleads.v15.errors.types import ( + conversion_upload_error as gage_conversion_upload_error, +) +from google.ads.googleads.v15.errors.types import date_error as gage_date_error +from google.ads.googleads.v15.errors.types import ( + distinct_error as gage_distinct_error, +) +from google.ads.googleads.v15.errors.types import ( + field_error as gage_field_error, +) +from google.ads.googleads.v15.errors.types import ( + mutate_error as gage_mutate_error, +) +from google.ads.googleads.v15.errors.types import ( + not_allowlisted_error as gage_not_allowlisted_error, +) +from google.ads.googleads.v15.errors.types import ( + string_format_error as gage_string_format_error, +) +from google.ads.googleads.v15.errors.types import ( + string_length_error as gage_string_length_error, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "OfflineConversionUploadClientSummary", + "OfflineConversionSummary", + "OfflineConversionAlert", + "OfflineConversionError", + }, +) + + +class OfflineConversionUploadClientSummary(proto.Message): + r"""Offline conversion upload client summary. + Attributes: + resource_name (str): + Output only. The resource name of the offline conversion + upload client summary. Offline conversion upload client + summary resource names have the form: + + ``customers/{customer_id}/offlineConversionUploadClientSummaries/{client}`` + client (google.ads.googleads.v15.enums.types.OfflineEventUploadClientEnum.OfflineEventUploadClient): + Output only. Client type of the upload event. + status (google.ads.googleads.v15.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. + 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.v15.resources.types.OfflineConversionSummary]): + Output only. Summary of history stats by last + N days. + job_summaries (MutableSequence[google.ads.googleads.v15.resources.types.OfflineConversionSummary]): + Output only. Summary of history stats by last + N jobs. + alerts (MutableSequence[google.ads.googleads.v15.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, + ) + 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. + 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, + ) + 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.v15.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.v15.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.v15.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.v15.errors.types.ConversionUploadErrorEnum.ConversionUploadError): + Output only. Conversion upload error. + + This field is a member of `oneof`_ ``error_code``. + date_error (google.ads.googleads.v15.errors.types.DateErrorEnum.DateError): + Output only. Date error. + + This field is a member of `oneof`_ ``error_code``. + distinct_error (google.ads.googleads.v15.errors.types.DistinctErrorEnum.DistinctError): + Output only. Distinct error. + + This field is a member of `oneof`_ ``error_code``. + field_error (google.ads.googleads.v15.errors.types.FieldErrorEnum.FieldError): + Output only. Field error. + + This field is a member of `oneof`_ ``error_code``. + mutate_error (google.ads.googleads.v15.errors.types.MutateErrorEnum.MutateError): + Output only. Mutate error. + + This field is a member of `oneof`_ ``error_code``. + not_allowlisted_error (google.ads.googleads.v15.errors.types.NotAllowlistedErrorEnum.NotAllowlistedError): + Output only. Not allowlisted error. + + This field is a member of `oneof`_ ``error_code``. + string_format_error (google.ads.googleads.v15.errors.types.StringFormatErrorEnum.StringFormatError): + Output only. String format error. + + This field is a member of `oneof`_ ``error_code``. + string_length_error (google.ads.googleads.v15.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/v15/resources/types/offline_user_data_job.py b/google/ads/googleads/v15/resources/types/offline_user_data_job.py new file mode 100644 index 000000000..633141456 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/offline_user_data_job.py @@ -0,0 +1,159 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import offline_user_data +from google.ads.googleads.v15.enums.types import ( + offline_user_data_job_failure_reason, +) +from google.ads.googleads.v15.enums.types import ( + offline_user_data_job_match_rate_range, +) +from google.ads.googleads.v15.enums.types import offline_user_data_job_status +from google.ads.googleads.v15.enums.types import offline_user_data_job_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.OfflineUserDataJobTypeEnum.OfflineUserDataJobType): + Immutable. Type of the job. + status (google.ads.googleads.v15.enums.types.OfflineUserDataJobStatusEnum.OfflineUserDataJobStatus): + Output only. Status of the job. + failure_reason (google.ads.googleads.v15.enums.types.OfflineUserDataJobFailureReasonEnum.OfflineUserDataJobFailureReason): + Output only. Reason for the processing + failure, if status is FAILED. + operation_metadata (google.ads.googleads.v15.resources.types.OfflineUserDataJobMetadata): + Output only. Metadata of offline user data + job depicting match rate range. + customer_match_user_list_metadata (google.ads.googleads.v15.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.v15.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.v15.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/v15/resources/types/operating_system_version_constant.py b/google/ads/googleads/v15/resources/types/operating_system_version_constant.py new file mode 100644 index 000000000..1e0611f41 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/operating_system_version_constant.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + operating_system_version_operator_type, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/paid_organic_search_term_view.py b/google/ads/googleads/v15/resources/types/paid_organic_search_term_view.py new file mode 100644 index 000000000..1eb9337b4 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/paid_organic_search_term_view.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/parental_status_view.py b/google/ads/googleads/v15/resources/types/parental_status_view.py new file mode 100644 index 000000000..fdc9cd48f --- /dev/null +++ b/google/ads/googleads/v15/resources/types/parental_status_view.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/payments_account.py b/google/ads/googleads/v15/resources/types/payments_account.py new file mode 100644 index 000000000..dbe5004ce --- /dev/null +++ b/google/ads/googleads/v15/resources/types/payments_account.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/per_store_view.py b/google/ads/googleads/v15/resources/types/per_store_view.py new file mode 100644 index 000000000..f73083b18 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/per_store_view.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + place_id: str = proto.Field( + proto.STRING, + number=2, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/product_category_constant.py b/google/ads/googleads/v15/resources/types/product_category_constant.py new file mode 100644 index 000000000..f5b1167c3 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/product_category_constant.py @@ -0,0 +1,124 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import product_category_level +from google.ads.googleads.v15.enums.types import product_category_state + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.ProductCategoryLevelEnum.ProductCategoryLevel): + Output only. Level of the product category. + state (google.ads.googleads.v15.enums.types.ProductCategoryStateEnum.ProductCategoryState): + Output only. State of the product category. + localizations (MutableSequence[google.ads.googleads.v15.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/v15/resources/types/product_group_view.py b/google/ads/googleads/v15/resources/types/product_group_view.py new file mode 100644 index 000000000..a31c2cd5d --- /dev/null +++ b/google/ads/googleads/v15/resources/types/product_group_view.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/product_link.py b/google/ads/googleads/v15/resources/types/product_link.py new file mode 100644 index 000000000..575bc5021 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/product_link.py @@ -0,0 +1,176 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import linked_product_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "ProductLink", + "DataPartnerIdentifier", + "GoogleAdsIdentifier", + "MerchantCenterIdentifier", + }, +) + + +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.v15.enums.types.LinkedProductTypeEnum.LinkedProductType): + Output only. The type of the linked product. + data_partner (google.ads.googleads.v15.resources.types.DataPartnerIdentifier): + Immutable. Data partner link. + + This field is a member of `oneof`_ ``linked_product``. + google_ads (google.ads.googleads.v15.resources.types.GoogleAdsIdentifier): + Immutable. Google Ads link. + + This field is a member of `oneof`_ ``linked_product``. + merchant_center (google.ads.googleads.v15.resources.types.MerchantCenterIdentifier): + Immutable. Google Merchant Center link. + + This field is a member of `oneof`_ ``linked_product``. + """ + + 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", + ) + + +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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/product_link_invitation.py b/google/ads/googleads/v15/resources/types/product_link_invitation.py new file mode 100644 index 000000000..e0c3faabc --- /dev/null +++ b/google/ads/googleads/v15/resources/types/product_link_invitation.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import linked_product_type +from google.ads.googleads.v15.enums.types import product_link_invitation_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "ProductLinkInvitation", + "HotelCenterLinkInvitationIdentifier", + "MerchantCenterLinkInvitationIdentifier", + }, +) + + +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.v15.enums.types.ProductLinkInvitationStatusEnum.ProductLinkInvitationStatus): + Output only. The status of the product link + invitation. This field is read only. + type_ (google.ads.googleads.v15.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.v15.resources.types.HotelCenterLinkInvitationIdentifier): + Output only. Hotel link invitation. + + This field is a member of `oneof`_ ``invited_account``. + merchant_center (google.ads.googleads.v15.resources.types.MerchantCenterLinkInvitationIdentifier): + Output only. Merchant Center link invitation. + + This field is a member of `oneof`_ ``invited_account``. + """ + + 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", + ) + + +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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/qualifying_question.py b/google/ads/googleads/v15/resources/types/qualifying_question.py new file mode 100644 index 000000000..d2afed2b0 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/qualifying_question.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/recommendation.py b/google/ads/googleads/v15/resources/types/recommendation.py new file mode 100644 index 000000000..d5cae86b6 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/recommendation.py @@ -0,0 +1,1777 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import criteria +from google.ads.googleads.v15.enums.types import ( + app_bidding_goal as gage_app_bidding_goal, +) +from google.ads.googleads.v15.enums.types import keyword_match_type +from google.ads.googleads.v15.enums.types import recommendation_type +from google.ads.googleads.v15.enums.types import ( + shopping_add_products_to_campaign_recommendation_enum, +) +from google.ads.googleads.v15.enums.types import ( + target_cpa_opt_in_recommendation_goal, +) +from google.ads.googleads.v15.resources.types import ad as gagr_ad +from google.ads.googleads.v15.resources.types import asset + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.RecommendationTypeEnum.RecommendationType): + Output only. The type of recommendation. + impact (google.ads.googleads.v15.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 + + 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.v15.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.v15.resources.types.Recommendation.CampaignBudgetRecommendation): + Output only. The forecasting campaign budget + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + keyword_recommendation (google.ads.googleads.v15.resources.types.Recommendation.KeywordRecommendation): + Output only. The keyword recommendation. + + This field is a member of `oneof`_ ``recommendation``. + text_ad_recommendation (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.resources.types.Recommendation.CalloutAssetRecommendation): + Output only. The callout asset + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + sitelink_asset_recommendation (google.ads.googleads.v15.resources.types.Recommendation.SitelinkAssetRecommendation): + Output only. The sitelink asset + recommendation. + + This field is a member of `oneof`_ ``recommendation``. + call_asset_recommendation (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.resources.types.Recommendation.ForecastingSetTargetRoasRecommendation): + Output only. The set target ROAS + 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.v15.resources.types.Recommendation.RecommendationMetrics): + Output only. Base metrics at the time the + recommendation was generated. + potential_metrics (google.ads.googleads.v15.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``. + 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, + ) + 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.v15.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.v15.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.v15.common.types.KeywordInfo): + Output only. The recommended keyword. + search_terms (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.resources.types.Asset]): + Output only. New callout extension assets + recommended at the campaign level. + recommended_customer_callout_assets (MutableSequence[google.ads.googleads.v15.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.v15.resources.types.Asset]): + Output only. New sitelink assets recommended + at the campaign level. + recommended_customer_sitelink_assets (MutableSequence[google.ads.googleads.v15.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.v15.common.types.KeywordInfo): + Output only. The existing keyword where the + match type should be more broad. + recommended_match_type (google.ads.googleads.v15.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.v15.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.v15.resources.types.Ad): + Output only. The current ad to be updated. + recommended_assets (google.ads.googleads.v15.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.v15.resources.types.Ad): + Output only. The current ad to be updated. + recommended_ad (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.resources.types.Recommendation.TargetAdjustmentInfo): + Output only. The relevant information + describing the recommended target adjustment. + app_bidding_goal (google.ads.googleads.v15.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.v15.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. + """ + + asset_group: str = proto.Field( + proto.STRING, + number=1, + ) + + 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.v15.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", + ) + + 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, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/recommendation_subscription.py b/google/ads/googleads/v15/resources/types/recommendation_subscription.py new file mode 100644 index 000000000..5cf24d306 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/recommendation_subscription.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + recommendation_subscription_status, +) +from google.ads.googleads.v15.enums.types import recommendation_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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/v15/resources/types/remarketing_action.py b/google/ads/googleads/v15/resources/types/remarketing_action.py new file mode 100644 index 000000000..cf9a65c73 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/remarketing_action.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import tag_snippet + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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/v15/resources/types/search_term_view.py b/google/ads/googleads/v15/resources/types/search_term_view.py new file mode 100644 index 000000000..ce4d36ff9 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/search_term_view.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import search_term_targeting_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "SearchTermView", + }, +) + + +class SearchTermView(proto.Message): + r"""A search term view with metrics 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}/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.v15.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/v15/resources/types/shared_criterion.py b/google/ads/googleads/v15/resources/types/shared_criterion.py new file mode 100644 index 000000000..97c12e4ef --- /dev/null +++ b/google/ads/googleads/v15/resources/types/shared_criterion.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import criteria +from google.ads.googleads.v15.enums.types import criterion_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.CriterionTypeEnum.CriterionType): + Output only. The type of the criterion. + keyword (google.ads.googleads.v15.common.types.KeywordInfo): + Immutable. Keyword. + + This field is a member of `oneof`_ ``criterion``. + youtube_video (google.ads.googleads.v15.common.types.YouTubeVideoInfo): + Immutable. YouTube Video. + + This field is a member of `oneof`_ ``criterion``. + youtube_channel (google.ads.googleads.v15.common.types.YouTubeChannelInfo): + Immutable. YouTube Channel. + + This field is a member of `oneof`_ ``criterion``. + placement (google.ads.googleads.v15.common.types.PlacementInfo): + Immutable. Placement. + + This field is a member of `oneof`_ ``criterion``. + mobile_app_category (google.ads.googleads.v15.common.types.MobileAppCategoryInfo): + Immutable. Mobile App Category. + + This field is a member of `oneof`_ ``criterion``. + mobile_application (google.ads.googleads.v15.common.types.MobileApplicationInfo): + Immutable. Mobile application. + + This field is a member of `oneof`_ ``criterion``. + brand (google.ads.googleads.v15.common.types.BrandInfo): + Immutable. Brand. + + 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, + ) + 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/shared_set.py b/google/ads/googleads/v15/resources/types/shared_set.py new file mode 100644 index 000000000..98310f24b --- /dev/null +++ b/google/ads/googleads/v15/resources/types/shared_set.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import shared_set_status +from google.ads.googleads.v15.enums.types import shared_set_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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``. + """ + + 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/resources/types/shopping_performance_view.py b/google/ads/googleads/v15/resources/types/shopping_performance_view.py new file mode 100644 index 000000000..10e8ba9a4 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/shopping_performance_view.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "ShoppingPerformanceView", + }, +) + + +class ShoppingPerformanceView(proto.Message): + r"""Shopping performance view. + Provides Shopping 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. + + 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/v15/resources/types/smart_campaign_search_term_view.py b/google/ads/googleads/v15/resources/types/smart_campaign_search_term_view.py new file mode 100644 index 000000000..fb1f59071 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/smart_campaign_search_term_view.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/smart_campaign_setting.py b/google/ads/googleads/v15/resources/types/smart_campaign_setting.py new file mode 100644 index 000000000..b876b95cb --- /dev/null +++ b/google/ads/googleads/v15/resources/types/smart_campaign_setting.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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/v15/resources/types/third_party_app_analytics_link.py b/google/ads/googleads/v15/resources/types/third_party_app_analytics_link.py new file mode 100644 index 000000000..9b0b6df83 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/third_party_app_analytics_link.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/topic_constant.py b/google/ads/googleads/v15/resources/types/topic_constant.py new file mode 100644 index 000000000..137ed8ddb --- /dev/null +++ b/google/ads/googleads/v15/resources/types/topic_constant.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/topic_view.py b/google/ads/googleads/v15/resources/types/topic_view.py new file mode 100644 index 000000000..46f2fac73 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/topic_view.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/travel_activity_group_view.py b/google/ads/googleads/v15/resources/types/travel_activity_group_view.py new file mode 100644 index 000000000..298a76c8a --- /dev/null +++ b/google/ads/googleads/v15/resources/types/travel_activity_group_view.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/travel_activity_performance_view.py b/google/ads/googleads/v15/resources/types/travel_activity_performance_view.py new file mode 100644 index 000000000..1640c1a80 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/travel_activity_performance_view.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/user_interest.py b/google/ads/googleads/v15/resources/types/user_interest.py new file mode 100644 index 000000000..9a2e26309 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/user_interest.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import ( + criterion_category_availability, +) +from google.ads.googleads.v15.enums.types import user_interest_taxonomy_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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/v15/resources/types/user_list.py b/google/ads/googleads/v15/resources/types/user_list.py new file mode 100644 index 000000000..d58301da2 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/user_list.py @@ -0,0 +1,340 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.common.types import user_lists +from google.ads.googleads.v15.enums.types import ( + access_reason as gage_access_reason, +) +from google.ads.googleads.v15.enums.types import user_list_access_status +from google.ads.googleads.v15.enums.types import user_list_closing_reason +from google.ads.googleads.v15.enums.types import user_list_membership_status +from google.ads.googleads.v15.enums.types import user_list_size_range +from google.ads.googleads.v15.enums.types import user_list_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "UserList", + }, +) + + +class UserList(proto.Message): + r"""A user list. This is a list of users a customer may target. + 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. Depending on its access_reason, the + user list name may not be unique (for example, if + access_reason=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.v15.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. However, for CRM based userlists, this + field can be set to 10000 which means no expiration. + + It'll be ignored for logical_user_list. + + 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.v15.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.v15.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.v15.enums.types.UserListTypeEnum.UserListType): + Output only. Type of this list. + + This field is read-only. + closing_reason (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.common.types.RuleBasedUserListInfo): + User list generated by a rule. + + This field is a member of `oneof`_ ``user_list``. + logical_user_list (google.ads.googleads.v15.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.v15.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.v15.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/v15/resources/types/user_location_view.py b/google/ads/googleads/v15/resources/types/user_location_view.py new file mode 100644 index 000000000..81b7dd0fb --- /dev/null +++ b/google/ads/googleads/v15/resources/types/user_location_view.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/resources/types/video.py b/google/ads/googleads/v15/resources/types/video.py new file mode 100644 index 000000000..c37c25e28 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/video.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + manifest={ + "Video", + }, +) + + +class Video(proto.Message): + r"""A video. + .. _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/v15/resources/types/webpage_view.py b/google/ads/googleads/v15/resources/types/webpage_view.py new file mode 100644 index 000000000..438d09fd8 --- /dev/null +++ b/google/ads/googleads/v15/resources/types/webpage_view.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.resources", + marshal="google.ads.googleads.v15", + 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/v15/services/__init__.py b/google/ads/googleads/v15/services/__init__.py new file mode 100644 index 000000000..89a37dc92 --- /dev/null +++ b/google/ads/googleads/v15/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/v15/services/services/__init__.py b/google/ads/googleads/v15/services/services/__init__.py new file mode 100644 index 000000000..89a37dc92 --- /dev/null +++ b/google/ads/googleads/v15/services/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/v15/services/services/account_budget_proposal_service/__init__.py b/google/ads/googleads/v15/services/services/account_budget_proposal_service/__init__.py new file mode 100644 index 000000000..ead39c0cd --- /dev/null +++ b/google/ads/googleads/v15/services/services/account_budget_proposal_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AccountBudgetProposalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/account_budget_proposal_service/client.py b/google/ads/googleads/v15/services/services/account_budget_proposal_service/client.py new file mode 100644 index 000000000..89548ccdf --- /dev/null +++ b/google/ads/googleads/v15/services/services/account_budget_proposal_service/client.py @@ -0,0 +1,588 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + account_budget_proposal_service, +) +from .transports.base import ( + AccountBudgetProposalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AccountBudgetProposalServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AccountBudgetProposalServiceTransport): + # transport is a AccountBudgetProposalServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAccountBudgetProposalRequest, dict, None]): + The request object. Request message for + [AccountBudgetProposalService.MutateAccountBudgetProposal][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operation]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a account_budget_proposal_service.MutateAccountBudgetProposalRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AccountBudgetProposalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/account_budget_proposal_service/transports/__init__.py b/google/ads/googleads/v15/services/services/account_budget_proposal_service/transports/__init__.py new file mode 100644 index 000000000..63618a7ac --- /dev/null +++ b/google/ads/googleads/v15/services/services/account_budget_proposal_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AccountBudgetProposalServiceTransport]] +_transport_registry["grpc"] = AccountBudgetProposalServiceGrpcTransport + +__all__ = ( + "AccountBudgetProposalServiceTransport", + "AccountBudgetProposalServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/account_budget_proposal_service/transports/base.py b/google/ads/googleads/v15/services/services/account_budget_proposal_service/transports/base.py new file mode 100644 index 000000000..151087768 --- /dev/null +++ b/google/ads/googleads/v15/services/services/account_budget_proposal_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + account_budget_proposal_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AccountBudgetProposalServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/account_budget_proposal_service/transports/grpc.py b/google/ads/googleads/v15/services/services/account_budget_proposal_service/transports/grpc.py new file mode 100644 index 000000000..4ee8d7c96 --- /dev/null +++ b/google/ads/googleads/v15/services/services/account_budget_proposal_service/transports/grpc.py @@ -0,0 +1,296 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + account_budget_proposal_service, +) +from .base import AccountBudgetProposalServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AccountBudgetProposalServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/account_link_service/__init__.py b/google/ads/googleads/v15/services/services/account_link_service/__init__.py new file mode 100644 index 000000000..bb912a5e3 --- /dev/null +++ b/google/ads/googleads/v15/services/services/account_link_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AccountLinkServiceClient",) diff --git a/google/ads/googleads/v15/services/services/account_link_service/client.py b/google/ads/googleads/v15/services/services/account_link_service/client.py new file mode 100644 index 000000000..68755e9dd --- /dev/null +++ b/google/ads/googleads/v15/services/services/account_link_service/client.py @@ -0,0 +1,638 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.resources.types import ( + account_link as gagr_account_link, +) +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AccountLinkServiceTransport): + # transport is a AccountLinkServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.CreateAccountLinkRequest, dict, None]): + The request object. Request message for + [AccountLinkService.CreateAccountLink][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.CreateAccountLinkResponse: + Response message for + [AccountLinkService.CreateAccountLink][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, account_link]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a account_link_service.CreateAccountLinkRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.MutateAccountLinkRequest, dict, None]): + The request object. Request message for + [AccountLinkService.MutateAccountLink][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operation]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a account_link_service.MutateAccountLinkRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AccountLinkServiceClient",) diff --git a/google/ads/googleads/v15/services/services/account_link_service/transports/__init__.py b/google/ads/googleads/v15/services/services/account_link_service/transports/__init__.py new file mode 100644 index 000000000..7b7c399a3 --- /dev/null +++ b/google/ads/googleads/v15/services/services/account_link_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AccountLinkServiceTransport]] +_transport_registry["grpc"] = AccountLinkServiceGrpcTransport + +__all__ = ( + "AccountLinkServiceTransport", + "AccountLinkServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/account_link_service/transports/base.py b/google/ads/googleads/v15/services/services/account_link_service/transports/base.py new file mode 100644 index 000000000..3fd6a9377 --- /dev/null +++ b/google/ads/googleads/v15/services/services/account_link_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import account_link_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AccountLinkServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/account_link_service/transports/grpc.py b/google/ads/googleads/v15/services/services/account_link_service/transports/grpc.py new file mode 100644 index 000000000..16088a083 --- /dev/null +++ b/google/ads/googleads/v15/services/services/account_link_service/transports/grpc.py @@ -0,0 +1,316 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import account_link_service +from .base import AccountLinkServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AccountLinkServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_ad_label_service/__init__.py b/google/ads/googleads/v15/services/services/ad_group_ad_label_service/__init__.py new file mode 100644 index 000000000..238ede6c0 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_ad_label_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AdGroupAdLabelServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_ad_label_service/client.py b/google/ads/googleads/v15/services/services/ad_group_ad_label_service/client.py new file mode 100644 index 000000000..da678afc6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_ad_label_service/client.py @@ -0,0 +1,578 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdGroupAdLabelServiceTransport): + # transport is a AdGroupAdLabelServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAdGroupAdLabelsRequest, dict, None]): + The request object. Request message for + [AdGroupAdLabelService.MutateAdGroupAdLabels][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_group_ad_label_service.MutateAdGroupAdLabelsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdGroupAdLabelServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_ad_label_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_group_ad_label_service/transports/__init__.py new file mode 100644 index 000000000..0d5b22ba7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_ad_label_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupAdLabelServiceTransport]] +_transport_registry["grpc"] = AdGroupAdLabelServiceGrpcTransport + +__all__ = ( + "AdGroupAdLabelServiceTransport", + "AdGroupAdLabelServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_group_ad_label_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_group_ad_label_service/transports/base.py new file mode 100644 index 000000000..9898eae22 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_ad_label_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_ad_label_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AdGroupAdLabelServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_ad_label_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_group_ad_label_service/transports/grpc.py new file mode 100644 index 000000000..e2cf85aa9 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_ad_label_service/transports/grpc.py @@ -0,0 +1,282 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_ad_label_service +from .base import AdGroupAdLabelServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AdGroupAdLabelServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_ad_service/__init__.py b/google/ads/googleads/v15/services/services/ad_group_ad_service/__init__.py new file mode 100644 index 000000000..0e8c28f55 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_ad_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AdGroupAdServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_ad_service/client.py b/google/ads/googleads/v15/services/services/ad_group_ad_service/client.py new file mode 100644 index 000000000..b2b33b0c8 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_ad_service/client.py @@ -0,0 +1,608 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdGroupAdServiceTransport): + # transport is a AdGroupAdServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAdGroupAdsRequest, dict, None]): + The request object. Request message for + [AdGroupAdService.MutateAdGroupAds][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_group_ad_service.MutateAdGroupAdsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdGroupAdServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_ad_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_group_ad_service/transports/__init__.py new file mode 100644 index 000000000..7838c072d --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_ad_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupAdServiceTransport]] +_transport_registry["grpc"] = AdGroupAdServiceGrpcTransport + +__all__ = ( + "AdGroupAdServiceTransport", + "AdGroupAdServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_group_ad_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_group_ad_service/transports/base.py new file mode 100644 index 000000000..77f23b671 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_ad_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_ad_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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, + ), + } + + 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() + + +__all__ = ("AdGroupAdServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_ad_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_group_ad_service/transports/grpc.py new file mode 100644 index 000000000..86dd309af --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_ad_service/transports/grpc.py @@ -0,0 +1,294 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_ad_service +from .base import AdGroupAdServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("AdGroupAdServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_asset_service/__init__.py b/google/ads/googleads/v15/services/services/ad_group_asset_service/__init__.py new file mode 100644 index 000000000..5c91600c9 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_asset_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AdGroupAssetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_asset_service/client.py b/google/ads/googleads/v15/services/services/ad_group_asset_service/client.py new file mode 100644 index 000000000..fd2a8174e --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_asset_service/client.py @@ -0,0 +1,573 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdGroupAssetServiceTransport): + # transport is a AdGroupAssetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAdGroupAssetsRequest, dict, None]): + The request object. Request message for + [AdGroupAssetService.MutateAdGroupAssets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_group_asset_service.MutateAdGroupAssetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdGroupAssetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_asset_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_group_asset_service/transports/__init__.py new file mode 100644 index 000000000..291a2bf5f --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_asset_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupAssetServiceTransport]] +_transport_registry["grpc"] = AdGroupAssetServiceGrpcTransport + +__all__ = ( + "AdGroupAssetServiceTransport", + "AdGroupAssetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_group_asset_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_group_asset_service/transports/base.py new file mode 100644 index 000000000..3f842ce52 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_asset_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_asset_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AdGroupAssetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_asset_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_group_asset_service/transports/grpc.py new file mode 100644 index 000000000..102af66aa --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_asset_service/transports/grpc.py @@ -0,0 +1,282 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_asset_service +from .base import AdGroupAssetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AdGroupAssetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_asset_set_service/__init__.py b/google/ads/googleads/v15/services/services/ad_group_asset_set_service/__init__.py new file mode 100644 index 000000000..0c2c670dd --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_asset_set_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AdGroupAssetSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_asset_set_service/client.py b/google/ads/googleads/v15/services/services/ad_group_asset_set_service/client.py new file mode 100644 index 000000000..58a8a3faa --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_asset_set_service/client.py @@ -0,0 +1,574 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdGroupAssetSetServiceTransport): + # transport is a AdGroupAssetSetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> ad_group_asset_set_service.MutateAdGroupAssetSetsResponse: + r"""Creates, or removes ad group asset sets. Operation + statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateAdGroupAssetSetsRequest, dict, None]): + The request object. Request message for + [AdGroupAssetSetService.MutateAdGroupAssetSets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_group_asset_set_service.MutateAdGroupAssetSetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdGroupAssetSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_asset_set_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_group_asset_set_service/transports/__init__.py new file mode 100644 index 000000000..b0af106bb --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_asset_set_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupAssetSetServiceTransport]] +_transport_registry["grpc"] = AdGroupAssetSetServiceGrpcTransport + +__all__ = ( + "AdGroupAssetSetServiceTransport", + "AdGroupAssetSetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_group_asset_set_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_group_asset_set_service/transports/base.py new file mode 100644 index 000000000..8b048b558 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_asset_set_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_asset_set_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AdGroupAssetSetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_asset_set_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_group_asset_set_service/transports/grpc.py new file mode 100644 index 000000000..d75b59ad8 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_asset_set_service/transports/grpc.py @@ -0,0 +1,276 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_asset_set_service +from .base import AdGroupAssetSetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AdGroupAssetSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/__init__.py b/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/__init__.py new file mode 100644 index 000000000..47573ddbb --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AdGroupBidModifierServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/client.py b/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/client.py new file mode 100644 index 000000000..b1aff2af0 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/client.py @@ -0,0 +1,576 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdGroupBidModifierServiceTransport): + # transport is a AdGroupBidModifierServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAdGroupBidModifiersRequest, dict, None]): + The request object. Request message for + [AdGroupBidModifierService.MutateAdGroupBidModifiers][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_group_bid_modifier_service.MutateAdGroupBidModifiersRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdGroupBidModifierServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/transports/__init__.py new file mode 100644 index 000000000..2a601ab15 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupBidModifierServiceTransport]] +_transport_registry["grpc"] = AdGroupBidModifierServiceGrpcTransport + +__all__ = ( + "AdGroupBidModifierServiceTransport", + "AdGroupBidModifierServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/transports/base.py new file mode 100644 index 000000000..8ff22405c --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + ad_group_bid_modifier_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AdGroupBidModifierServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/transports/grpc.py new file mode 100644 index 000000000..4182d590e --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_bid_modifier_service/transports/grpc.py @@ -0,0 +1,291 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + ad_group_bid_modifier_service, +) +from .base import AdGroupBidModifierServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AdGroupBidModifierServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/__init__.py b/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/__init__.py new file mode 100644 index 000000000..34fa2f6a6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AdGroupCriterionCustomizerServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/client.py b/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/client.py new file mode 100644 index 000000000..3db0e8bf7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/client.py @@ -0,0 +1,588 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdGroupCriterionCustomizerServiceTransport): + # transport is a AdGroupCriterionCustomizerServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAdGroupCriterionCustomizersRequest, dict, None]): + The request object. Request message for + [AdGroupCriterionCustomizerService.MutateAdGroupCriterionCustomizers][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_group_criterion_customizer_service.MutateAdGroupCriterionCustomizersRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdGroupCriterionCustomizerServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/transports/__init__.py new file mode 100644 index 000000000..d91ceb3dc --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupCriterionCustomizerServiceTransport]] +_transport_registry["grpc"] = AdGroupCriterionCustomizerServiceGrpcTransport + +__all__ = ( + "AdGroupCriterionCustomizerServiceTransport", + "AdGroupCriterionCustomizerServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/transports/base.py new file mode 100644 index 000000000..a51cfe48a --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + ad_group_criterion_customizer_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AdGroupCriterionCustomizerServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/transports/grpc.py new file mode 100644 index 000000000..f252538ff --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_customizer_service/transports/grpc.py @@ -0,0 +1,286 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + ad_group_criterion_customizer_service, +) +from .base import ( + AdGroupCriterionCustomizerServiceTransport, + DEFAULT_CLIENT_INFO, +) + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AdGroupCriterionCustomizerServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/__init__.py b/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/__init__.py new file mode 100644 index 000000000..ea075ede0 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AdGroupCriterionLabelServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/client.py b/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/client.py new file mode 100644 index 000000000..f24c63318 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/client.py @@ -0,0 +1,591 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdGroupCriterionLabelServiceTransport): + # transport is a AdGroupCriterionLabelServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAdGroupCriterionLabelsRequest, dict, None]): + The request object. Request message for + [AdGroupCriterionLabelService.MutateAdGroupCriterionLabels][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_group_criterion_label_service.MutateAdGroupCriterionLabelsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdGroupCriterionLabelServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/transports/__init__.py new file mode 100644 index 000000000..3cfb8383d --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupCriterionLabelServiceTransport]] +_transport_registry["grpc"] = AdGroupCriterionLabelServiceGrpcTransport + +__all__ = ( + "AdGroupCriterionLabelServiceTransport", + "AdGroupCriterionLabelServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/transports/base.py new file mode 100644 index 000000000..4117496d1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + ad_group_criterion_label_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AdGroupCriterionLabelServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/transports/grpc.py new file mode 100644 index 000000000..ccfdf6ae0 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_label_service/transports/grpc.py @@ -0,0 +1,286 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + ad_group_criterion_label_service, +) +from .base import AdGroupCriterionLabelServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AdGroupCriterionLabelServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_service/__init__.py b/google/ads/googleads/v15/services/services/ad_group_criterion_service/__init__.py new file mode 100644 index 000000000..dd70b46ea --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AdGroupCriterionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_service/client.py b/google/ads/googleads/v15/services/services/ad_group_criterion_service/client.py new file mode 100644 index 000000000..e74261984 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_service/client.py @@ -0,0 +1,649 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdGroupCriterionServiceTransport): + # transport is a AdGroupCriterionServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAdGroupCriteriaRequest, dict, None]): + The request object. Request message for + [AdGroupCriterionService.MutateAdGroupCriteria][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_group_criterion_service.MutateAdGroupCriteriaRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdGroupCriterionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_group_criterion_service/transports/__init__.py new file mode 100644 index 000000000..fd4a35af5 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupCriterionServiceTransport]] +_transport_registry["grpc"] = AdGroupCriterionServiceGrpcTransport + +__all__ = ( + "AdGroupCriterionServiceTransport", + "AdGroupCriterionServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_group_criterion_service/transports/base.py new file mode 100644 index 000000000..dd6eb89f3 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_criterion_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AdGroupCriterionServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_criterion_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_group_criterion_service/transports/grpc.py new file mode 100644 index 000000000..f3b815e81 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_criterion_service/transports/grpc.py @@ -0,0 +1,292 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_criterion_service +from .base import AdGroupCriterionServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AdGroupCriterionServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_customizer_service/__init__.py b/google/ads/googleads/v15/services/services/ad_group_customizer_service/__init__.py new file mode 100644 index 000000000..83d64799c --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_customizer_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AdGroupCustomizerServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_customizer_service/client.py b/google/ads/googleads/v15/services/services/ad_group_customizer_service/client.py new file mode 100644 index 000000000..5f5f50cb7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_customizer_service/client.py @@ -0,0 +1,583 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdGroupCustomizerServiceTransport): + # transport is a AdGroupCustomizerServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> ad_group_customizer_service.MutateAdGroupCustomizersResponse: + r"""Creates, updates or removes ad group customizers. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateAdGroupCustomizersRequest, dict, None]): + The request object. Request message for + [AdGroupCustomizerService.MutateAdGroupCustomizers][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_group_customizer_service.MutateAdGroupCustomizersRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdGroupCustomizerServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_customizer_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_group_customizer_service/transports/__init__.py new file mode 100644 index 000000000..6bdadc71c --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_customizer_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupCustomizerServiceTransport]] +_transport_registry["grpc"] = AdGroupCustomizerServiceGrpcTransport + +__all__ = ( + "AdGroupCustomizerServiceTransport", + "AdGroupCustomizerServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_group_customizer_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_group_customizer_service/transports/base.py new file mode 100644 index 000000000..fabfc8d69 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_customizer_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_customizer_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AdGroupCustomizerServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_customizer_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_group_customizer_service/transports/grpc.py new file mode 100644 index 000000000..497a33cb7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_customizer_service/transports/grpc.py @@ -0,0 +1,276 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_customizer_service +from .base import AdGroupCustomizerServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AdGroupCustomizerServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/__init__.py b/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/__init__.py new file mode 100644 index 000000000..70b8f1fc7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 AdGroupExtensionSettingServiceClient + +__all__ = ("AdGroupExtensionSettingServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/client.py b/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/client.py new file mode 100644 index 000000000..af6fc5397 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/client.py @@ -0,0 +1,600 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + ad_group_extension_setting_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + AdGroupExtensionSettingServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AdGroupExtensionSettingServiceGrpcTransport + + +class AdGroupExtensionSettingServiceClientMeta(type): + """Metaclass for the AdGroupExtensionSettingService 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[AdGroupExtensionSettingServiceTransport]] + _transport_registry["grpc"] = AdGroupExtensionSettingServiceGrpcTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdGroupExtensionSettingServiceTransport]: + """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 AdGroupExtensionSettingServiceClient( + metaclass=AdGroupExtensionSettingServiceClientMeta +): + """Service to manage ad group extension 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + AdGroupExtensionSettingServiceClient: 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: + AdGroupExtensionSettingServiceClient: 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) -> AdGroupExtensionSettingServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupExtensionSettingServiceTransport: The transport used by the client + instance. + """ + return self._transport + + def __enter__(self) -> "AdGroupExtensionSettingServiceClient": + 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() + + @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_extension_setting_path( + customer_id: str, + ad_group_id: str, + extension_type: str, + ) -> str: + """Returns a fully-qualified ad_group_extension_setting string.""" + return "customers/{customer_id}/adGroupExtensionSettings/{ad_group_id}~{extension_type}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + extension_type=extension_type, + ) + + @staticmethod + def parse_ad_group_extension_setting_path(path: str) -> Dict[str, str]: + """Parses a ad_group_extension_setting path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupExtensionSettings/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def extension_feed_item_path( + customer_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified extension_feed_item string.""" + return ( + "customers/{customer_id}/extensionFeedItems/{feed_item_id}".format( + customer_id=customer_id, + feed_item_id=feed_item_id, + ) + ) + + @staticmethod + def parse_extension_feed_item_path(path: str) -> Dict[str, str]: + """Parses a extension_feed_item path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/extensionFeedItems/(?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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, AdGroupExtensionSettingServiceTransport] + ] = 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 extension 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, AdGroupExtensionSettingServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdGroupExtensionSettingServiceTransport): + # transport is a AdGroupExtensionSettingServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def mutate_ad_group_extension_settings( + self, + request: Optional[ + Union[ + ad_group_extension_setting_service.MutateAdGroupExtensionSettingsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + ad_group_extension_setting_service.AdGroupExtensionSettingOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> ad_group_extension_setting_service.MutateAdGroupExtensionSettingsResponse: + r"""Creates, updates, or removes ad group extension settings. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `CriterionError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `ExtensionSettingError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateAdGroupExtensionSettingsRequest, dict, None]): + The request object. Request message for + [AdGroupExtensionSettingService.MutateAdGroupExtensionSettings][google.ads.googleads.v15.services.AdGroupExtensionSettingService.MutateAdGroupExtensionSettings]. + customer_id (str): + Required. The ID of the customer + whose ad group extension 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.v15.services.types.AdGroupExtensionSettingOperation]): + Required. The list of operations to + perform on individual ad group extension + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateAdGroupExtensionSettingsResponse: + Response message for an ad group + extension setting 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_group_extension_setting_service.MutateAdGroupExtensionSettingsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, + ad_group_extension_setting_service.MutateAdGroupExtensionSettingsRequest, + ): + request = ad_group_extension_setting_service.MutateAdGroupExtensionSettingsRequest( + request + ) + # 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_extension_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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdGroupExtensionSettingServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/transports/__init__.py new file mode 100644 index 000000000..71cad8b9c --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 AdGroupExtensionSettingServiceTransport +from .grpc import AdGroupExtensionSettingServiceGrpcTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupExtensionSettingServiceTransport]] +_transport_registry["grpc"] = AdGroupExtensionSettingServiceGrpcTransport + +__all__ = ( + "AdGroupExtensionSettingServiceTransport", + "AdGroupExtensionSettingServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/transports/base.py new file mode 100644 index 000000000..e4bc1382f --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + ad_group_extension_setting_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class AdGroupExtensionSettingServiceTransport(abc.ABC): + """Abstract transport class for AdGroupExtensionSettingService.""" + + 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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_group_extension_settings: gapic_v1.method.wrap_method( + self.mutate_ad_group_extension_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 mutate_ad_group_extension_settings( + self, + ) -> Callable[ + [ + ad_group_extension_setting_service.MutateAdGroupExtensionSettingsRequest + ], + Union[ + ad_group_extension_setting_service.MutateAdGroupExtensionSettingsResponse, + Awaitable[ + ad_group_extension_setting_service.MutateAdGroupExtensionSettingsResponse + ], + ], + ]: + raise NotImplementedError() + + +__all__ = ("AdGroupExtensionSettingServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/transports/grpc.py new file mode 100644 index 000000000..b171a11ef --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_extension_setting_service/transports/grpc.py @@ -0,0 +1,297 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + ad_group_extension_setting_service, +) +from .base import AdGroupExtensionSettingServiceTransport, DEFAULT_CLIENT_INFO + + +class AdGroupExtensionSettingServiceGrpcTransport( + AdGroupExtensionSettingServiceTransport +): + """gRPC backend transport for AdGroupExtensionSettingService. + + Service to manage ad group extension 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def mutate_ad_group_extension_settings( + self, + ) -> Callable[ + [ + ad_group_extension_setting_service.MutateAdGroupExtensionSettingsRequest + ], + ad_group_extension_setting_service.MutateAdGroupExtensionSettingsResponse, + ]: + r"""Return a callable for the mutate ad group extension + settings method over gRPC. + + Creates, updates, or removes ad group extension settings. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `CriterionError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `ExtensionSettingError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateAdGroupExtensionSettingsRequest], + ~.MutateAdGroupExtensionSettingsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_extension_settings" not in self._stubs: + self._stubs[ + "mutate_ad_group_extension_settings" + ] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.AdGroupExtensionSettingService/MutateAdGroupExtensionSettings", + request_serializer=ad_group_extension_setting_service.MutateAdGroupExtensionSettingsRequest.serialize, + response_deserializer=ad_group_extension_setting_service.MutateAdGroupExtensionSettingsResponse.deserialize, + ) + return self._stubs["mutate_ad_group_extension_settings"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("AdGroupExtensionSettingServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_feed_service/__init__.py b/google/ads/googleads/v15/services/services/ad_group_feed_service/__init__.py new file mode 100644 index 000000000..1b3f803c7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_feed_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 AdGroupFeedServiceClient + +__all__ = ("AdGroupFeedServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_feed_service/client.py b/google/ads/googleads/v15/services/services/ad_group_feed_service/client.py new file mode 100644 index 000000000..6d4460850 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_feed_service/client.py @@ -0,0 +1,574 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_feed_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import AdGroupFeedServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import AdGroupFeedServiceGrpcTransport + + +class AdGroupFeedServiceClientMeta(type): + """Metaclass for the AdGroupFeedService 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[AdGroupFeedServiceTransport]] + _transport_registry["grpc"] = AdGroupFeedServiceGrpcTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AdGroupFeedServiceTransport]: + """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 AdGroupFeedServiceClient(metaclass=AdGroupFeedServiceClientMeta): + """Service to manage ad group feeds.""" + + @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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + AdGroupFeedServiceClient: 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: + AdGroupFeedServiceClient: 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) -> AdGroupFeedServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AdGroupFeedServiceTransport: The transport used by the client + instance. + """ + return self._transport + + def __enter__(self) -> "AdGroupFeedServiceClient": + 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() + + @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_feed_path( + customer_id: str, + ad_group_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified ad_group_feed string.""" + return "customers/{customer_id}/adGroupFeeds/{ad_group_id}~{feed_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_ad_group_feed_path(path: str) -> Dict[str, str]: + """Parses a ad_group_feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupFeeds/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_path( + customer_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified feed string.""" + return "customers/{customer_id}/feeds/{feed_id}".format( + customer_id=customer_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_feed_path(path: str) -> Dict[str, str]: + """Parses a feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feeds/(?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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, AdGroupFeedServiceTransport]] = 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 feed 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, AdGroupFeedServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdGroupFeedServiceTransport): + # transport is a AdGroupFeedServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def mutate_ad_group_feeds( + self, + request: Optional[ + Union[ad_group_feed_service.MutateAdGroupFeedsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ad_group_feed_service.AdGroupFeedOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> ad_group_feed_service.MutateAdGroupFeedsResponse: + r"""Creates, updates, or removes ad group feeds. Operation statuses + are returned. + + List of thrown errors: `AdGroupFeedError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CollectionSizeError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FunctionError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `MutateError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateAdGroupFeedsRequest, dict, None]): + The request object. Request message for + [AdGroupFeedService.MutateAdGroupFeeds][google.ads.googleads.v15.services.AdGroupFeedService.MutateAdGroupFeeds]. + customer_id (str): + Required. The ID of the customer + whose ad group feeds 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.v15.services.types.AdGroupFeedOperation]): + Required. The list of operations to + perform on individual ad group feeds. + + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateAdGroupFeedsResponse: + Response message for an ad group feed + 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_group_feed_service.MutateAdGroupFeedsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, ad_group_feed_service.MutateAdGroupFeedsRequest + ): + request = ad_group_feed_service.MutateAdGroupFeedsRequest(request) + # 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_feeds + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdGroupFeedServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_feed_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_group_feed_service/transports/__init__.py new file mode 100644 index 000000000..3c4b5ce9a --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_feed_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 AdGroupFeedServiceTransport +from .grpc import AdGroupFeedServiceGrpcTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupFeedServiceTransport]] +_transport_registry["grpc"] = AdGroupFeedServiceGrpcTransport + +__all__ = ( + "AdGroupFeedServiceTransport", + "AdGroupFeedServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_group_feed_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_group_feed_service/transports/base.py new file mode 100644 index 000000000..e32135664 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_feed_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_feed_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class AdGroupFeedServiceTransport(abc.ABC): + """Abstract transport class for AdGroupFeedService.""" + + 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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_ad_group_feeds: gapic_v1.method.wrap_method( + self.mutate_ad_group_feeds, + 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_feeds( + self, + ) -> Callable[ + [ad_group_feed_service.MutateAdGroupFeedsRequest], + Union[ + ad_group_feed_service.MutateAdGroupFeedsResponse, + Awaitable[ad_group_feed_service.MutateAdGroupFeedsResponse], + ], + ]: + raise NotImplementedError() + + +__all__ = ("AdGroupFeedServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_feed_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_group_feed_service/transports/grpc.py new file mode 100644 index 000000000..cc4e604ba --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_feed_service/transports/grpc.py @@ -0,0 +1,286 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_feed_service +from .base import AdGroupFeedServiceTransport, DEFAULT_CLIENT_INFO + + +class AdGroupFeedServiceGrpcTransport(AdGroupFeedServiceTransport): + """gRPC backend transport for AdGroupFeedService. + + Service to manage ad group feeds. + + This 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def mutate_ad_group_feeds( + self, + ) -> Callable[ + [ad_group_feed_service.MutateAdGroupFeedsRequest], + ad_group_feed_service.MutateAdGroupFeedsResponse, + ]: + r"""Return a callable for the mutate ad group feeds method over gRPC. + + Creates, updates, or removes ad group feeds. Operation statuses + are returned. + + List of thrown errors: `AdGroupFeedError <>`__ + `AuthenticationError <>`__ `AuthorizationError <>`__ + `CollectionSizeError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FunctionError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `MutateError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateAdGroupFeedsRequest], + ~.MutateAdGroupFeedsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_feeds" not in self._stubs: + self._stubs[ + "mutate_ad_group_feeds" + ] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.AdGroupFeedService/MutateAdGroupFeeds", + request_serializer=ad_group_feed_service.MutateAdGroupFeedsRequest.serialize, + response_deserializer=ad_group_feed_service.MutateAdGroupFeedsResponse.deserialize, + ) + return self._stubs["mutate_ad_group_feeds"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("AdGroupFeedServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_label_service/__init__.py b/google/ads/googleads/v15/services/services/ad_group_label_service/__init__.py new file mode 100644 index 000000000..654d87bd1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_label_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AdGroupLabelServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_label_service/client.py b/google/ads/googleads/v15/services/services/ad_group_label_service/client.py new file mode 100644 index 000000000..c52a1b4d6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_label_service/client.py @@ -0,0 +1,570 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdGroupLabelServiceTransport): + # transport is a AdGroupLabelServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAdGroupLabelsRequest, dict, None]): + The request object. Request message for + [AdGroupLabelService.MutateAdGroupLabels][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_group_label_service.MutateAdGroupLabelsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdGroupLabelServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_label_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_group_label_service/transports/__init__.py new file mode 100644 index 000000000..f9e7e1d8b --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_label_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupLabelServiceTransport]] +_transport_registry["grpc"] = AdGroupLabelServiceGrpcTransport + +__all__ = ( + "AdGroupLabelServiceTransport", + "AdGroupLabelServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_group_label_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_group_label_service/transports/base.py new file mode 100644 index 000000000..069afaa86 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_label_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_label_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AdGroupLabelServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_label_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_group_label_service/transports/grpc.py new file mode 100644 index 000000000..6539f8379 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_label_service/transports/grpc.py @@ -0,0 +1,282 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_label_service +from .base import AdGroupLabelServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AdGroupLabelServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_service/__init__.py b/google/ads/googleads/v15/services/services/ad_group_service/__init__.py new file mode 100644 index 000000000..e65109908 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AdGroupServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_service/client.py b/google/ads/googleads/v15/services/services/ad_group_service/client.py new file mode 100644 index 000000000..e90b142af --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_service/client.py @@ -0,0 +1,576 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdGroupServiceTransport): + # transport is a AdGroupServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAdGroupsRequest, dict, None]): + The request object. Request message for + [AdGroupService.MutateAdGroups][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_group_service.MutateAdGroupsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdGroupServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_group_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_group_service/transports/__init__.py new file mode 100644 index 000000000..2068e683d --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdGroupServiceTransport]] +_transport_registry["grpc"] = AdGroupServiceGrpcTransport + +__all__ = ( + "AdGroupServiceTransport", + "AdGroupServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_group_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_group_service/transports/base.py new file mode 100644 index 000000000..2a551bb49 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AdGroupServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_group_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_group_service/transports/grpc.py new file mode 100644 index 000000000..80e91bb76 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_group_service/transports/grpc.py @@ -0,0 +1,289 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ad_group_service +from .base import AdGroupServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AdGroupServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_parameter_service/__init__.py b/google/ads/googleads/v15/services/services/ad_parameter_service/__init__.py new file mode 100644 index 000000000..d0e091909 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_parameter_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AdParameterServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_parameter_service/client.py b/google/ads/googleads/v15/services/services/ad_parameter_service/client.py new file mode 100644 index 000000000..307024a18 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_parameter_service/client.py @@ -0,0 +1,555 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdParameterServiceTransport): + # transport is a AdParameterServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAdParametersRequest, dict, None]): + The request object. Request message for + [AdParameterService.MutateAdParameters][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_parameter_service.MutateAdParametersRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdParameterServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_parameter_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_parameter_service/transports/__init__.py new file mode 100644 index 000000000..d13260be5 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_parameter_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AdParameterServiceTransport]] +_transport_registry["grpc"] = AdParameterServiceGrpcTransport + +__all__ = ( + "AdParameterServiceTransport", + "AdParameterServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_parameter_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_parameter_service/transports/base.py new file mode 100644 index 000000000..534b94679 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_parameter_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ad_parameter_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AdParameterServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_parameter_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_parameter_service/transports/grpc.py new file mode 100644 index 000000000..7faefe1ca --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_parameter_service/transports/grpc.py @@ -0,0 +1,280 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ad_parameter_service +from .base import AdParameterServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AdParameterServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_service/__init__.py b/google/ads/googleads/v15/services/services/ad_service/__init__.py new file mode 100644 index 000000000..ffe0a831e --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AdServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_service/client.py b/google/ads/googleads/v15/services/services/ad_service/client.py new file mode 100644 index 000000000..0556f5b95 --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_service/client.py @@ -0,0 +1,611 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.resources.types import ad +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AdServiceTransport): + # transport is a AdServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def get_ad( + self, + request: Optional[Union[ad_service.GetAdRequest, 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, str]] = (), + ) -> ad.Ad: + r"""Returns the requested ad in full detail. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.GetAdRequest, dict, None]): + The request object. Request message for + [AdService.GetAd][google.ads.googleads.v15.services.AdService.GetAd]. + resource_name (str): + Required. The resource name of the ad + to fetch. + + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.resources.types.Ad: + An ad. + """ + # Create or coerce a protobuf request object. + # Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([resource_name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_service.GetAdRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, ad_service.GetAdRequest): + request = ad_service.GetAdRequest(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_ad] + + # 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAdsRequest, dict, None]): + The request object. Request message for + [AdService.MutateAds][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a ad_service.MutateAdsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AdServiceClient",) diff --git a/google/ads/googleads/v15/services/services/ad_service/transports/__init__.py b/google/ads/googleads/v15/services/services/ad_service/transports/__init__.py new file mode 100644 index 000000000..1745572dc --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_service/transports/__init__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = OrderedDict() # type: Dict[str, Type[AdServiceTransport]] +_transport_registry["grpc"] = AdServiceGrpcTransport + +__all__ = ( + "AdServiceTransport", + "AdServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/ad_service/transports/base.py b/google/ads/googleads/v15/services/services/ad_service/transports/base.py new file mode 100644 index 000000000..e9810f04e --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_service/transports/base.py @@ -0,0 +1,168 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.resources.types import ad +from google.ads.googleads.v15.services.types import ad_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.get_ad: gapic_v1.method.wrap_method( + self.get_ad, + default_timeout=None, + client_info=client_info, + ), + 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 get_ad( + self, + ) -> Callable[[ad_service.GetAdRequest], Union[ad.Ad, Awaitable[ad.Ad]]]: + raise NotImplementedError() + + @property + def mutate_ads( + self, + ) -> Callable[ + [ad_service.MutateAdsRequest], + Union[ + ad_service.MutateAdsResponse, + Awaitable[ad_service.MutateAdsResponse], + ], + ]: + raise NotImplementedError() + + +__all__ = ("AdServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/ad_service/transports/grpc.py b/google/ads/googleads/v15/services/services/ad_service/transports/grpc.py new file mode 100644 index 000000000..f0ab7446a --- /dev/null +++ b/google/ads/googleads/v15/services/services/ad_service/transports/grpc.py @@ -0,0 +1,318 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.resources.types import ad +from google.ads.googleads.v15.services.types import ad_service +from .base import AdServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def get_ad(self) -> Callable[[ad_service.GetAdRequest], ad.Ad]: + r"""Return a callable for the get ad method over gRPC. + + Returns the requested ad in full detail. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.GetAdRequest], + ~.Ad]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_ad" not in self._stubs: + self._stubs["get_ad"] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.AdService/GetAd", + request_serializer=ad_service.GetAdRequest.serialize, + response_deserializer=ad.Ad.deserialize, + ) + return self._stubs["get_ad"] + + @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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.AdService/MutateAds", + request_serializer=ad_service.MutateAdsRequest.serialize, + response_deserializer=ad_service.MutateAdsResponse.deserialize, + ) + return self._stubs["mutate_ads"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("AdServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_group_asset_service/__init__.py b/google/ads/googleads/v15/services/services/asset_group_asset_service/__init__.py new file mode 100644 index 000000000..acdc36cb4 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_asset_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AssetGroupAssetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_group_asset_service/client.py b/google/ads/googleads/v15/services/services/asset_group_asset_service/client.py new file mode 100644 index 000000000..592b8738e --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_asset_service/client.py @@ -0,0 +1,573 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AssetGroupAssetServiceTransport): + # transport is a AssetGroupAssetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> asset_group_asset_service.MutateAssetGroupAssetsResponse: + r"""Creates, updates or removes asset group assets. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateAssetGroupAssetsRequest, dict, None]): + The request object. Request message for + [AssetGroupAssetService.MutateAssetGroupAssets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a asset_group_asset_service.MutateAssetGroupAssetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AssetGroupAssetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_group_asset_service/transports/__init__.py b/google/ads/googleads/v15/services/services/asset_group_asset_service/transports/__init__.py new file mode 100644 index 000000000..29585dda3 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_asset_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetGroupAssetServiceTransport]] +_transport_registry["grpc"] = AssetGroupAssetServiceGrpcTransport + +__all__ = ( + "AssetGroupAssetServiceTransport", + "AssetGroupAssetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/asset_group_asset_service/transports/base.py b/google/ads/googleads/v15/services/services/asset_group_asset_service/transports/base.py new file mode 100644 index 000000000..e19def307 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_asset_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import asset_group_asset_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AssetGroupAssetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_group_asset_service/transports/grpc.py b/google/ads/googleads/v15/services/services/asset_group_asset_service/transports/grpc.py new file mode 100644 index 000000000..c959118a6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_asset_service/transports/grpc.py @@ -0,0 +1,276 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import asset_group_asset_service +from .base import AssetGroupAssetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AssetGroupAssetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/__init__.py b/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/__init__.py new file mode 100644 index 000000000..ad6590c82 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AssetGroupListingGroupFilterServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/client.py b/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/client.py new file mode 100644 index 000000000..c7539990b --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/client.py @@ -0,0 +1,569 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + asset_group_listing_group_filter_service, +) +from .transports.base import ( + AssetGroupListingGroupFilterServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AssetGroupListingGroupFilterServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AssetGroupListingGroupFilterServiceTransport): + # transport is a AssetGroupListingGroupFilterServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAssetGroupListingGroupFiltersRequest, dict, None]): + The request object. Request message for + [AssetGroupListingGroupFilterService.MutateAssetGroupListingGroupFilters][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a asset_group_listing_group_filter_service.MutateAssetGroupListingGroupFiltersRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AssetGroupListingGroupFilterServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/transports/__init__.py b/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/transports/__init__.py new file mode 100644 index 000000000..470d8bb97 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetGroupListingGroupFilterServiceTransport]] +_transport_registry["grpc"] = AssetGroupListingGroupFilterServiceGrpcTransport + +__all__ = ( + "AssetGroupListingGroupFilterServiceTransport", + "AssetGroupListingGroupFilterServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/transports/base.py b/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/transports/base.py new file mode 100644 index 000000000..bdb183ddc --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + asset_group_listing_group_filter_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AssetGroupListingGroupFilterServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/transports/grpc.py b/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/transports/grpc.py new file mode 100644 index 000000000..a753c288f --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_listing_group_filter_service/transports/grpc.py @@ -0,0 +1,286 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + asset_group_listing_group_filter_service, +) +from .base import ( + AssetGroupListingGroupFilterServiceTransport, + DEFAULT_CLIENT_INFO, +) + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AssetGroupListingGroupFilterServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_group_service/__init__.py b/google/ads/googleads/v15/services/services/asset_group_service/__init__.py new file mode 100644 index 000000000..f7af182f5 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AssetGroupServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_group_service/client.py b/google/ads/googleads/v15/services/services/asset_group_service/client.py new file mode 100644 index 000000000..f83b83ab9 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_service/client.py @@ -0,0 +1,543 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AssetGroupServiceTransport): + # transport is a AssetGroupServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> asset_group_service.MutateAssetGroupsResponse: + r"""Creates, updates or removes asset groups. Operation + statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateAssetGroupsRequest, dict, None]): + The request object. Request message for + [AssetGroupService.MutateAssetGroups][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a asset_group_service.MutateAssetGroupsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AssetGroupServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_group_service/transports/__init__.py b/google/ads/googleads/v15/services/services/asset_group_service/transports/__init__.py new file mode 100644 index 000000000..6e19ea416 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetGroupServiceTransport]] +_transport_registry["grpc"] = AssetGroupServiceGrpcTransport + +__all__ = ( + "AssetGroupServiceTransport", + "AssetGroupServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/asset_group_service/transports/base.py b/google/ads/googleads/v15/services/services/asset_group_service/transports/base.py new file mode 100644 index 000000000..a4a1051f0 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import asset_group_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AssetGroupServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_group_service/transports/grpc.py b/google/ads/googleads/v15/services/services/asset_group_service/transports/grpc.py new file mode 100644 index 000000000..688f046ad --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_service/transports/grpc.py @@ -0,0 +1,274 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import asset_group_service +from .base import AssetGroupServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AssetGroupServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_group_signal_service/__init__.py b/google/ads/googleads/v15/services/services/asset_group_signal_service/__init__.py new file mode 100644 index 000000000..9f92996eb --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_signal_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AssetGroupSignalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_group_signal_service/client.py b/google/ads/googleads/v15/services/services/asset_group_signal_service/client.py new file mode 100644 index 000000000..014aab31d --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_signal_service/client.py @@ -0,0 +1,560 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AssetGroupSignalServiceTransport): + # transport is a AssetGroupSignalServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> asset_group_signal_service.MutateAssetGroupSignalsResponse: + r"""Creates or removes asset group signals. Operation + statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateAssetGroupSignalsRequest, dict, None]): + The request object. Request message for + [AssetGroupSignalService.MutateAssetGroupSignals][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a asset_group_signal_service.MutateAssetGroupSignalsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AssetGroupSignalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_group_signal_service/transports/__init__.py b/google/ads/googleads/v15/services/services/asset_group_signal_service/transports/__init__.py new file mode 100644 index 000000000..36ced0aec --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_signal_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetGroupSignalServiceTransport]] +_transport_registry["grpc"] = AssetGroupSignalServiceGrpcTransport + +__all__ = ( + "AssetGroupSignalServiceTransport", + "AssetGroupSignalServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/asset_group_signal_service/transports/base.py b/google/ads/googleads/v15/services/services/asset_group_signal_service/transports/base.py new file mode 100644 index 000000000..4f8cea217 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_signal_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import asset_group_signal_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AssetGroupSignalServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_group_signal_service/transports/grpc.py b/google/ads/googleads/v15/services/services/asset_group_signal_service/transports/grpc.py new file mode 100644 index 000000000..e84c94e06 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_group_signal_service/transports/grpc.py @@ -0,0 +1,276 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import asset_group_signal_service +from .base import AssetGroupSignalServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AssetGroupSignalServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_service/__init__.py b/google/ads/googleads/v15/services/services/asset_service/__init__.py new file mode 100644 index 000000000..690028f5d --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AssetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_service/client.py b/google/ads/googleads/v15/services/services/asset_service/client.py new file mode 100644 index 000000000..11593b832 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_service/client.py @@ -0,0 +1,551 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AssetServiceTransport): + # transport is a AssetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateAssetsRequest, dict, None]): + The request object. Request message for + [AssetService.MutateAssets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a asset_service.MutateAssetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AssetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_service/transports/__init__.py b/google/ads/googleads/v15/services/services/asset_service/transports/__init__.py new file mode 100644 index 000000000..d495d4aa2 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetServiceTransport]] +_transport_registry["grpc"] = AssetServiceGrpcTransport + +__all__ = ( + "AssetServiceTransport", + "AssetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/asset_service/transports/base.py b/google/ads/googleads/v15/services/services/asset_service/transports/base.py new file mode 100644 index 000000000..6d597ac9a --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import asset_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AssetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_service/transports/grpc.py b/google/ads/googleads/v15/services/services/asset_service/transports/grpc.py new file mode 100644 index 000000000..f5722540d --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_service/transports/grpc.py @@ -0,0 +1,287 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import asset_service +from .base import AssetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.AssetService/MutateAssets", + request_serializer=asset_service.MutateAssetsRequest.serialize, + response_deserializer=asset_service.MutateAssetsResponse.deserialize, + ) + return self._stubs["mutate_assets"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("AssetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_set_asset_service/__init__.py b/google/ads/googleads/v15/services/services/asset_set_asset_service/__init__.py new file mode 100644 index 000000000..f18d29239 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_set_asset_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AssetSetAssetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_set_asset_service/client.py b/google/ads/googleads/v15/services/services/asset_set_asset_service/client.py new file mode 100644 index 000000000..c25f0a998 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_set_asset_service/client.py @@ -0,0 +1,567 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AssetSetAssetServiceTransport): + # transport is a AssetSetAssetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> asset_set_asset_service.MutateAssetSetAssetsResponse: + r"""Creates, updates or removes asset set assets. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateAssetSetAssetsRequest, dict, None]): + The request object. Request message for + [AssetSetAssetService.MutateAssetSetAssets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a asset_set_asset_service.MutateAssetSetAssetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AssetSetAssetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_set_asset_service/transports/__init__.py b/google/ads/googleads/v15/services/services/asset_set_asset_service/transports/__init__.py new file mode 100644 index 000000000..0213a82d9 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_set_asset_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetSetAssetServiceTransport]] +_transport_registry["grpc"] = AssetSetAssetServiceGrpcTransport + +__all__ = ( + "AssetSetAssetServiceTransport", + "AssetSetAssetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/asset_set_asset_service/transports/base.py b/google/ads/googleads/v15/services/services/asset_set_asset_service/transports/base.py new file mode 100644 index 000000000..6b51fd48f --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_set_asset_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import asset_set_asset_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AssetSetAssetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_set_asset_service/transports/grpc.py b/google/ads/googleads/v15/services/services/asset_set_asset_service/transports/grpc.py new file mode 100644 index 000000000..98b3edf95 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_set_asset_service/transports/grpc.py @@ -0,0 +1,276 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import asset_set_asset_service +from .base import AssetSetAssetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AssetSetAssetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_set_service/__init__.py b/google/ads/googleads/v15/services/services/asset_set_service/__init__.py new file mode 100644 index 000000000..fa90506a2 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_set_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AssetSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_set_service/client.py b/google/ads/googleads/v15/services/services/asset_set_service/client.py new file mode 100644 index 000000000..01260db20 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_set_service/client.py @@ -0,0 +1,521 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AssetSetServiceTransport): + # transport is a AssetSetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> asset_set_service.MutateAssetSetsResponse: + r"""Creates, updates or removes asset sets. Operation + statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateAssetSetsRequest, dict, None]): + The request object. Request message for + [AssetSetService.MutateAssetSets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a asset_set_service.MutateAssetSetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AssetSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/asset_set_service/transports/__init__.py b/google/ads/googleads/v15/services/services/asset_set_service/transports/__init__.py new file mode 100644 index 000000000..1df350e01 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_set_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AssetSetServiceTransport]] +_transport_registry["grpc"] = AssetSetServiceGrpcTransport + +__all__ = ( + "AssetSetServiceTransport", + "AssetSetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/asset_set_service/transports/base.py b/google/ads/googleads/v15/services/services/asset_set_service/transports/base.py new file mode 100644 index 000000000..a161d6bf8 --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_set_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import asset_set_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AssetSetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/asset_set_service/transports/grpc.py b/google/ads/googleads/v15/services/services/asset_set_service/transports/grpc.py new file mode 100644 index 000000000..6b1b71d1f --- /dev/null +++ b/google/ads/googleads/v15/services/services/asset_set_service/transports/grpc.py @@ -0,0 +1,274 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import asset_set_service +from .base import AssetSetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("AssetSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/audience_insights_service/__init__.py b/google/ads/googleads/v15/services/services/audience_insights_service/__init__.py new file mode 100644 index 000000000..4ccc85027 --- /dev/null +++ b/google/ads/googleads/v15/services/services/audience_insights_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AudienceInsightsServiceClient",) diff --git a/google/ads/googleads/v15/services/services/audience_insights_service/client.py b/google/ads/googleads/v15/services/services/audience_insights_service/client.py new file mode 100644 index 000000000..ea7a5f18c --- /dev/null +++ b/google/ads/googleads/v15/services/services/audience_insights_service/client.py @@ -0,0 +1,959 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.enums.types import audience_insights_dimension +from google.ads.googleads.v15.services.types import audience_insights_service +from .transports.base import ( + AudienceInsightsServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import AudienceInsightsServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AudienceInsightsServiceTransport): + # transport is a AudienceInsightsServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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.BasicInsightsAudience + ] = None, + specific_audience: Optional[ + audience_insights_service.BasicInsightsAudience + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> 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.v15.services.types.GenerateInsightsFinderReportRequest, dict, None]): + The request object. Request message for + [AudienceInsightsService.GenerateInsightsFinderReport][google.ads.googleads.v15.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.v15.services.types.BasicInsightsAudience): + 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.v15.services.types.BasicInsightsAudience): + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.GenerateInsightsFinderReportResponse: + The response message for + [AudienceInsightsService.GenerateInsightsFinderReport][google.ads.googleads.v15.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. + has_flattened_params = any( + [customer_id, baseline_audience, specific_audience] + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a audience_insights_service.GenerateInsightsFinderReportRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.ListAudienceInsightsAttributesRequest, dict, None]): + The request object. Request message for + [AudienceInsightsService.ListAudienceInsightsAttributes][google.ads.googleads.v15.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.v15.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]): + Required. The types of attributes to + be returned. + + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.ListAudienceInsightsAttributesResponse: + Response message for + [AudienceInsightsService.ListAudienceInsightsAttributes][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, dimensions, query_text]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a audience_insights_service.ListAudienceInsightsAttributesRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.ListInsightsEligibleDatesRequest, dict, None]): + The request object. Request message for + [AudienceInsightsService.ListInsightsEligibleDates][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.ListInsightsEligibleDatesResponse: + Response message for + [AudienceInsightsService.ListInsightsEligibleDates][google.ads.googleads.v15.services.AudienceInsightsService.ListInsightsEligibleDates]. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a audience_insights_service.ListInsightsEligibleDatesRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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 + ] + + # 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, str]] = (), + ) -> 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.v15.services.types.GenerateAudienceCompositionInsightsRequest, dict, None]): + The request object. Request message for + [AudienceInsightsService.GenerateAudienceCompositionInsights][google.ads.googleads.v15.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.v15.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.v15.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]): + Required. The audience dimensions for + which composition insights should be + returned. + + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.GenerateAudienceCompositionInsightsResponse: + Response message for + [AudienceInsightsService.GenerateAudienceCompositionInsights][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, audience, dimensions]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a audience_insights_service.GenerateAudienceCompositionInsightsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, + *, + customer_id: Optional[str] = None, + 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, str]] = (), + ) -> 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.v15.services.types.GenerateSuggestedTargetingInsightsRequest, dict, None]): + The request object. Request message for + [AudienceInsightsService.GenerateSuggestedTargetingInsights][google.ads.googleads.v15.services.AudienceInsightsService.GenerateSuggestedTargetingInsights]. + 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.v15.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. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.GenerateSuggestedTargetingInsightsResponse: + Response message for + [AudienceInsightsService.GenerateSuggestedTargetingInsights][google.ads.googleads.v15.services.AudienceInsightsService.GenerateSuggestedTargetingInsights]. + + """ + # Create or coerce a protobuf request object. + # Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([customer_id, audience]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a audience_insights_service.GenerateSuggestedTargetingInsightsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, + audience_insights_service.GenerateSuggestedTargetingInsightsRequest, + ): + request = audience_insights_service.GenerateSuggestedTargetingInsightsRequest( + request + ) + # 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 + + # 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AudienceInsightsServiceClient",) diff --git a/google/ads/googleads/v15/services/services/audience_insights_service/transports/__init__.py b/google/ads/googleads/v15/services/services/audience_insights_service/transports/__init__.py new file mode 100644 index 000000000..eb9e6677e --- /dev/null +++ b/google/ads/googleads/v15/services/services/audience_insights_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AudienceInsightsServiceTransport]] +_transport_registry["grpc"] = AudienceInsightsServiceGrpcTransport + +__all__ = ( + "AudienceInsightsServiceTransport", + "AudienceInsightsServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/audience_insights_service/transports/base.py b/google/ads/googleads/v15/services/services/audience_insights_service/transports/base.py new file mode 100644 index 000000000..30975580d --- /dev/null +++ b/google/ads/googleads/v15/services/services/audience_insights_service/transports/base.py @@ -0,0 +1,234 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import audience_insights_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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_suggested_targeting_insights: gapic_v1.method.wrap_method( + self.generate_suggested_targeting_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_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_suggested_targeting_insights( + self, + ) -> Callable[ + [audience_insights_service.GenerateSuggestedTargetingInsightsRequest], + Union[ + audience_insights_service.GenerateSuggestedTargetingInsightsResponse, + Awaitable[ + audience_insights_service.GenerateSuggestedTargetingInsightsResponse + ], + ], + ]: + raise NotImplementedError() + + +__all__ = ("AudienceInsightsServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/audience_insights_service/transports/grpc.py b/google/ads/googleads/v15/services/services/audience_insights_service/transports/grpc.py new file mode 100644 index 000000000..9982f4d2e --- /dev/null +++ b/google/ads/googleads/v15/services/services/audience_insights_service/transports/grpc.py @@ -0,0 +1,436 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import audience_insights_service +from .base import AudienceInsightsServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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_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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.AudienceInsightsService/GenerateSuggestedTargetingInsights", + request_serializer=audience_insights_service.GenerateSuggestedTargetingInsightsRequest.serialize, + response_deserializer=audience_insights_service.GenerateSuggestedTargetingInsightsResponse.deserialize, + ) + return self._stubs["generate_suggested_targeting_insights"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("AudienceInsightsServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/audience_service/__init__.py b/google/ads/googleads/v15/services/services/audience_service/__init__.py new file mode 100644 index 000000000..fc83e7b04 --- /dev/null +++ b/google/ads/googleads/v15/services/services/audience_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("AudienceServiceClient",) diff --git a/google/ads/googleads/v15/services/services/audience_service/client.py b/google/ads/googleads/v15/services/services/audience_service/client.py new file mode 100644 index 000000000..0f470ca7c --- /dev/null +++ b/google/ads/googleads/v15/services/services/audience_service/client.py @@ -0,0 +1,540 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, AudienceServiceTransport): + # transport is a AudienceServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> audience_service.MutateAudiencesResponse: + r"""Creates audiences. Operation statuses are returned. + + List of thrown errors: `AudienceError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateAudiencesRequest, dict, None]): + The request object. Request message for + [AudienceService.MutateAudiences][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a audience_service.MutateAudiencesRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("AudienceServiceClient",) diff --git a/google/ads/googleads/v15/services/services/audience_service/transports/__init__.py b/google/ads/googleads/v15/services/services/audience_service/transports/__init__.py new file mode 100644 index 000000000..184e9d823 --- /dev/null +++ b/google/ads/googleads/v15/services/services/audience_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[AudienceServiceTransport]] +_transport_registry["grpc"] = AudienceServiceGrpcTransport + +__all__ = ( + "AudienceServiceTransport", + "AudienceServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/audience_service/transports/base.py b/google/ads/googleads/v15/services/services/audience_service/transports/base.py new file mode 100644 index 000000000..186ffece6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/audience_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import audience_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("AudienceServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/audience_service/transports/grpc.py b/google/ads/googleads/v15/services/services/audience_service/transports/grpc.py new file mode 100644 index 000000000..48b15c4d4 --- /dev/null +++ b/google/ads/googleads/v15/services/services/audience_service/transports/grpc.py @@ -0,0 +1,275 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import audience_service +from .base import AudienceServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.AudienceService/MutateAudiences", + request_serializer=audience_service.MutateAudiencesRequest.serialize, + response_deserializer=audience_service.MutateAudiencesResponse.deserialize, + ) + return self._stubs["mutate_audiences"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("AudienceServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/batch_job_service/__init__.py b/google/ads/googleads/v15/services/services/batch_job_service/__init__.py new file mode 100644 index 000000000..54782e108 --- /dev/null +++ b/google/ads/googleads/v15/services/services/batch_job_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("BatchJobServiceClient",) diff --git a/google/ads/googleads/v15/services/services/batch_job_service/client.py b/google/ads/googleads/v15/services/services/batch_job_service/client.py new file mode 100644 index 000000000..040860ffa --- /dev/null +++ b/google/ads/googleads/v15/services/services/batch_job_service/client.py @@ -0,0 +1,2586 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.resources.types import batch_job +from google.ads.googleads.v15.services.services.batch_job_service import pagers +from google.ads.googleads.v15.services.types import batch_job_service +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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_extension_setting_path( + customer_id: str, + ad_group_id: str, + extension_type: str, + ) -> str: + """Returns a fully-qualified ad_group_extension_setting string.""" + return "customers/{customer_id}/adGroupExtensionSettings/{ad_group_id}~{extension_type}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + extension_type=extension_type, + ) + + @staticmethod + def parse_ad_group_extension_setting_path(path: str) -> Dict[str, str]: + """Parses a ad_group_extension_setting path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupExtensionSettings/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_feed_path( + customer_id: str, + ad_group_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified ad_group_feed string.""" + return "customers/{customer_id}/adGroupFeeds/{ad_group_id}~{feed_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_ad_group_feed_path(path: str) -> Dict[str, str]: + """Parses a ad_group_feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupFeeds/(?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_extension_setting_path( + customer_id: str, + campaign_id: str, + extension_type: str, + ) -> str: + """Returns a fully-qualified campaign_extension_setting string.""" + return "customers/{customer_id}/campaignExtensionSettings/{campaign_id}~{extension_type}".format( + customer_id=customer_id, + campaign_id=campaign_id, + extension_type=extension_type, + ) + + @staticmethod + def parse_campaign_extension_setting_path(path: str) -> Dict[str, str]: + """Parses a campaign_extension_setting path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignExtensionSettings/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_feed_path( + customer_id: str, + campaign_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified campaign_feed string.""" + return "customers/{customer_id}/campaignFeeds/{campaign_id}~{feed_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_campaign_feed_path(path: str) -> Dict[str, str]: + """Parses a campaign_feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignFeeds/(?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 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_extension_setting_path( + customer_id: str, + extension_type: str, + ) -> str: + """Returns a fully-qualified customer_extension_setting string.""" + return "customers/{customer_id}/customerExtensionSettings/{extension_type}".format( + customer_id=customer_id, + extension_type=extension_type, + ) + + @staticmethod + def parse_customer_extension_setting_path(path: str) -> Dict[str, str]: + """Parses a customer_extension_setting path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerExtensionSettings/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_feed_path( + customer_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified customer_feed string.""" + return "customers/{customer_id}/customerFeeds/{feed_id}".format( + customer_id=customer_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_customer_feed_path(path: str) -> Dict[str, str]: + """Parses a customer_feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerFeeds/(?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 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 extension_feed_item_path( + customer_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified extension_feed_item string.""" + return ( + "customers/{customer_id}/extensionFeedItems/{feed_item_id}".format( + customer_id=customer_id, + feed_item_id=feed_item_id, + ) + ) + + @staticmethod + def parse_extension_feed_item_path(path: str) -> Dict[str, str]: + """Parses a extension_feed_item path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/extensionFeedItems/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_path( + customer_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified feed string.""" + return "customers/{customer_id}/feeds/{feed_id}".format( + customer_id=customer_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_feed_path(path: str) -> Dict[str, str]: + """Parses a feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feeds/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_item_path( + customer_id: str, + feed_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified feed_item string.""" + return ( + "customers/{customer_id}/feedItems/{feed_id}~{feed_item_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_id=feed_item_id, + ) + ) + + @staticmethod + def parse_feed_item_path(path: str) -> Dict[str, str]: + """Parses a feed_item path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItems/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_item_set_path( + customer_id: str, + feed_id: str, + feed_item_set_id: str, + ) -> str: + """Returns a fully-qualified feed_item_set string.""" + return "customers/{customer_id}/feedItemSets/{feed_id}~{feed_item_set_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_set_id=feed_item_set_id, + ) + + @staticmethod + def parse_feed_item_set_path(path: str) -> Dict[str, str]: + """Parses a feed_item_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItemSets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_item_set_link_path( + customer_id: str, + feed_id: str, + feed_item_set_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified feed_item_set_link string.""" + return "customers/{customer_id}/feedItemSetLinks/{feed_id}~{feed_item_set_id}~{feed_item_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_set_id=feed_item_set_id, + feed_item_id=feed_item_id, + ) + + @staticmethod + def parse_feed_item_set_link_path(path: str) -> Dict[str, str]: + """Parses a feed_item_set_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItemSetLinks/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_item_target_path( + customer_id: str, + feed_id: str, + feed_item_id: str, + feed_item_target_type: str, + feed_item_target_id: str, + ) -> str: + """Returns a fully-qualified feed_item_target string.""" + return "customers/{customer_id}/feedItemTargets/{feed_id}~{feed_item_id}~{feed_item_target_type}~{feed_item_target_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_id=feed_item_id, + feed_item_target_type=feed_item_target_type, + feed_item_target_id=feed_item_target_id, + ) + + @staticmethod + def parse_feed_item_target_path(path: str) -> Dict[str, str]: + """Parses a feed_item_target path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItemTargets/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_mapping_path( + customer_id: str, + feed_id: str, + feed_mapping_id: str, + ) -> str: + """Returns a fully-qualified feed_mapping string.""" + return "customers/{customer_id}/feedMappings/{feed_id}~{feed_mapping_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_mapping_id=feed_mapping_id, + ) + + @staticmethod + def parse_feed_mapping_path(path: str) -> Dict[str, str]: + """Parses a feed_mapping path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedMappings/(?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 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 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 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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, BatchJobServiceTransport): + # transport is a BatchJobServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateBatchJobRequest, dict, None]): + The request object. Request message for + [BatchJobService.MutateBatchJob][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateBatchJobResponse: + Response message for + [BatchJobService.MutateBatchJob][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operation]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a batch_job_service.MutateBatchJobRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.ListBatchJobResultsRequest, dict, None]): + The request object. Request message for + [BatchJobService.ListBatchJobResults][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.services.batch_job_service.pagers.ListBatchJobResultsPager: + Response message for + [BatchJobService.ListBatchJobResults][google.ads.googleads.v15.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. + has_flattened_params = any([resource_name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a batch_job_service.ListBatchJobResultsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, + 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, str]] = (), + ) -> 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.v15.services.types.RunBatchJobRequest, dict, None]): + The request object. Request message for + [BatchJobService.RunBatchJob][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.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. + has_flattened_params = any([resource_name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a batch_job_service.RunBatchJobRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.AddBatchJobOperationsRequest, dict, None]): + The request object. Request message for + [BatchJobService.AddBatchJobOperations][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.AddBatchJobOperationsResponse: + Response message for + [BatchJobService.AddBatchJobOperations][google.ads.googleads.v15.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. + has_flattened_params = any( + [resource_name, sequence_token, mutate_operations] + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a batch_job_service.AddBatchJobOperationsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("BatchJobServiceClient",) diff --git a/google/ads/googleads/v15/services/services/batch_job_service/pagers.py b/google/ads/googleads/v15/services/services/batch_job_service/pagers.py new file mode 100644 index 000000000..bb9cf17c7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/batch_job_service/pagers.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Any, Callable, Iterable, Iterator, Sequence, Tuple + +from google.ads.googleads.v15.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.v15.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.v15.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, + metadata: Sequence[Tuple[str, str]] = (), + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (:class:`google.ads.googleads.v15.services.types.ListBatchJobResultsRequest`): + The initial request object. + response (:class:`google.ads.googleads.v15.services.types.ListBatchJobResultsResponse`): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = batch_job_service.ListBatchJobResultsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages(self) -> Iterable[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, 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) diff --git a/google/ads/googleads/v15/services/services/batch_job_service/transports/__init__.py b/google/ads/googleads/v15/services/services/batch_job_service/transports/__init__.py new file mode 100644 index 000000000..68ea9434f --- /dev/null +++ b/google/ads/googleads/v15/services/services/batch_job_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[BatchJobServiceTransport]] +_transport_registry["grpc"] = BatchJobServiceGrpcTransport + +__all__ = ( + "BatchJobServiceTransport", + "BatchJobServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/batch_job_service/transports/base.py b/google/ads/googleads/v15/services/services/batch_job_service/transports/base.py new file mode 100644 index 000000000..2bbc70363 --- /dev/null +++ b/google/ads/googleads/v15/services/services/batch_job_service/transports/base.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import batch_job_service +from google.longrunning import operations_pb2 # type: ignore + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("BatchJobServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/batch_job_service/transports/grpc.py b/google/ads/googleads/v15/services/services/batch_job_service/transports/grpc.py new file mode 100644 index 000000000..b3a5d014f --- /dev/null +++ b/google/ads/googleads/v15/services/services/batch_job_service/transports/grpc.py @@ -0,0 +1,408 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import batch_job_service +from google.longrunning import operations_pb2 # type: ignore +from .base import BatchJobServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client: Optional[operations_v1.OperationsClient] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def operations_client(self) -> operations_v1.OperationsClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsClient( + self.grpc_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("BatchJobServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/__init__.py b/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/__init__.py new file mode 100644 index 000000000..8d9b60d86 --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("BiddingDataExclusionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/client.py b/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/client.py new file mode 100644 index 000000000..8419a508e --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/client.py @@ -0,0 +1,560 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, BiddingDataExclusionServiceTransport): + # transport is a BiddingDataExclusionServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> bidding_data_exclusion_service.MutateBiddingDataExclusionsResponse: + r"""Creates, updates, or removes data exclusions. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateBiddingDataExclusionsRequest, dict, None]): + The request object. Request message for + [BiddingDataExclusionService.MutateBiddingDataExclusions][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateBiddingDataExclusionsResponse: + Response message for data exlusions + 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a bidding_data_exclusion_service.MutateBiddingDataExclusionsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("BiddingDataExclusionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/transports/__init__.py b/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/transports/__init__.py new file mode 100644 index 000000000..371df073f --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[BiddingDataExclusionServiceTransport]] +_transport_registry["grpc"] = BiddingDataExclusionServiceGrpcTransport + +__all__ = ( + "BiddingDataExclusionServiceTransport", + "BiddingDataExclusionServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/transports/base.py b/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/transports/base.py new file mode 100644 index 000000000..d7c9a4842 --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + bidding_data_exclusion_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("BiddingDataExclusionServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/transports/grpc.py b/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/transports/grpc.py new file mode 100644 index 000000000..4eb82edb6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_data_exclusion_service/transports/grpc.py @@ -0,0 +1,280 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + bidding_data_exclusion_service, +) +from .base import BiddingDataExclusionServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("BiddingDataExclusionServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/__init__.py b/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/__init__.py new file mode 100644 index 000000000..ebf2e19c2 --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("BiddingSeasonalityAdjustmentServiceClient",) diff --git a/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/client.py b/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/client.py new file mode 100644 index 000000000..9dfcb8d06 --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/client.py @@ -0,0 +1,564 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, BiddingSeasonalityAdjustmentServiceTransport): + # transport is a BiddingSeasonalityAdjustmentServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsResponse: + r"""Creates, updates, or removes seasonality adjustments. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateBiddingSeasonalityAdjustmentsRequest, dict, None]): + The request object. Request message for + [BiddingSeasonalityAdjustmentService.MutateBiddingSeasonalityAdjustments][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a bidding_seasonality_adjustment_service.MutateBiddingSeasonalityAdjustmentsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("BiddingSeasonalityAdjustmentServiceClient",) diff --git a/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/transports/__init__.py b/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/transports/__init__.py new file mode 100644 index 000000000..7bf941dea --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[BiddingSeasonalityAdjustmentServiceTransport]] +_transport_registry["grpc"] = BiddingSeasonalityAdjustmentServiceGrpcTransport + +__all__ = ( + "BiddingSeasonalityAdjustmentServiceTransport", + "BiddingSeasonalityAdjustmentServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/transports/base.py b/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/transports/base.py new file mode 100644 index 000000000..960f6dc3b --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + bidding_seasonality_adjustment_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("BiddingSeasonalityAdjustmentServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/transports/grpc.py b/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/transports/grpc.py new file mode 100644 index 000000000..46138c5ba --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_seasonality_adjustment_service/transports/grpc.py @@ -0,0 +1,286 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + bidding_seasonality_adjustment_service, +) +from .base import ( + BiddingSeasonalityAdjustmentServiceTransport, + DEFAULT_CLIENT_INFO, +) + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("BiddingSeasonalityAdjustmentServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/bidding_strategy_service/__init__.py b/google/ads/googleads/v15/services/services/bidding_strategy_service/__init__.py new file mode 100644 index 000000000..6332feb0b --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_strategy_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("BiddingStrategyServiceClient",) diff --git a/google/ads/googleads/v15/services/services/bidding_strategy_service/client.py b/google/ads/googleads/v15/services/services/bidding_strategy_service/client.py new file mode 100644 index 000000000..ce7cbf26c --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_strategy_service/client.py @@ -0,0 +1,543 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, BiddingStrategyServiceTransport): + # transport is a BiddingStrategyServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateBiddingStrategiesRequest, dict, None]): + The request object. Request message for + [BiddingStrategyService.MutateBiddingStrategies][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a bidding_strategy_service.MutateBiddingStrategiesRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("BiddingStrategyServiceClient",) diff --git a/google/ads/googleads/v15/services/services/bidding_strategy_service/transports/__init__.py b/google/ads/googleads/v15/services/services/bidding_strategy_service/transports/__init__.py new file mode 100644 index 000000000..73a786255 --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_strategy_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[BiddingStrategyServiceTransport]] +_transport_registry["grpc"] = BiddingStrategyServiceGrpcTransport + +__all__ = ( + "BiddingStrategyServiceTransport", + "BiddingStrategyServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/bidding_strategy_service/transports/base.py b/google/ads/googleads/v15/services/services/bidding_strategy_service/transports/base.py new file mode 100644 index 000000000..d26cd25d1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_strategy_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import bidding_strategy_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("BiddingStrategyServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/bidding_strategy_service/transports/grpc.py b/google/ads/googleads/v15/services/services/bidding_strategy_service/transports/grpc.py new file mode 100644 index 000000000..9f669a193 --- /dev/null +++ b/google/ads/googleads/v15/services/services/bidding_strategy_service/transports/grpc.py @@ -0,0 +1,289 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import bidding_strategy_service +from .base import BiddingStrategyServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("BiddingStrategyServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/billing_setup_service/__init__.py b/google/ads/googleads/v15/services/services/billing_setup_service/__init__.py new file mode 100644 index 000000000..18c50d5fe --- /dev/null +++ b/google/ads/googleads/v15/services/services/billing_setup_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("BillingSetupServiceClient",) diff --git a/google/ads/googleads/v15/services/services/billing_setup_service/client.py b/google/ads/googleads/v15/services/services/billing_setup_service/client.py new file mode 100644 index 000000000..9f1a06958 --- /dev/null +++ b/google/ads/googleads/v15/services/services/billing_setup_service/client.py @@ -0,0 +1,547 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import billing_setup_service +from .transports.base import BillingSetupServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import BillingSetupServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, BillingSetupServiceTransport): + # transport is a BillingSetupServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateBillingSetupRequest, dict, None]): + 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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operation]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a billing_setup_service.MutateBillingSetupRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("BillingSetupServiceClient",) diff --git a/google/ads/googleads/v15/services/services/billing_setup_service/transports/__init__.py b/google/ads/googleads/v15/services/services/billing_setup_service/transports/__init__.py new file mode 100644 index 000000000..9c43f4334 --- /dev/null +++ b/google/ads/googleads/v15/services/services/billing_setup_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[BillingSetupServiceTransport]] +_transport_registry["grpc"] = BillingSetupServiceGrpcTransport + +__all__ = ( + "BillingSetupServiceTransport", + "BillingSetupServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/billing_setup_service/transports/base.py b/google/ads/googleads/v15/services/services/billing_setup_service/transports/base.py new file mode 100644 index 000000000..945a79eed --- /dev/null +++ b/google/ads/googleads/v15/services/services/billing_setup_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import billing_setup_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("BillingSetupServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/billing_setup_service/transports/grpc.py b/google/ads/googleads/v15/services/services/billing_setup_service/transports/grpc.py new file mode 100644 index 000000000..e1ec0227e --- /dev/null +++ b/google/ads/googleads/v15/services/services/billing_setup_service/transports/grpc.py @@ -0,0 +1,289 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import billing_setup_service +from .base import BillingSetupServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("BillingSetupServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/brand_suggestion_service/__init__.py b/google/ads/googleads/v15/services/services/brand_suggestion_service/__init__.py new file mode 100644 index 000000000..55b38fe62 --- /dev/null +++ b/google/ads/googleads/v15/services/services/brand_suggestion_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("BrandSuggestionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/brand_suggestion_service/client.py b/google/ads/googleads/v15/services/services/brand_suggestion_service/client.py new file mode 100644 index 000000000..865c22f17 --- /dev/null +++ b/google/ads/googleads/v15/services/services/brand_suggestion_service/client.py @@ -0,0 +1,491 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import brand_suggestion_service +from .transports.base import ( + BrandSuggestionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import BrandSuggestionServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, BrandSuggestionServiceTransport): + # transport is a BrandSuggestionServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.SuggestBrandsRequest, dict, None]): + The request object. Request message for + [BrandSuggestionService.SuggestBrands][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.SuggestBrandsResponse: + Response message for + [BrandSuggestionService.SuggestBrands][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, brand_prefix]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a brand_suggestion_service.SuggestBrandsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("BrandSuggestionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/brand_suggestion_service/transports/__init__.py b/google/ads/googleads/v15/services/services/brand_suggestion_service/transports/__init__.py new file mode 100644 index 000000000..10fa0dde6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/brand_suggestion_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[BrandSuggestionServiceTransport]] +_transport_registry["grpc"] = BrandSuggestionServiceGrpcTransport + +__all__ = ( + "BrandSuggestionServiceTransport", + "BrandSuggestionServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/brand_suggestion_service/transports/base.py b/google/ads/googleads/v15/services/services/brand_suggestion_service/transports/base.py new file mode 100644 index 000000000..1f2b49637 --- /dev/null +++ b/google/ads/googleads/v15/services/services/brand_suggestion_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import brand_suggestion_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("BrandSuggestionServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/brand_suggestion_service/transports/grpc.py b/google/ads/googleads/v15/services/services/brand_suggestion_service/transports/grpc.py new file mode 100644 index 000000000..acf841218 --- /dev/null +++ b/google/ads/googleads/v15/services/services/brand_suggestion_service/transports/grpc.py @@ -0,0 +1,274 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import brand_suggestion_service +from .base import BrandSuggestionServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("BrandSuggestionServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_asset_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_asset_service/__init__.py new file mode 100644 index 000000000..2d303e11a --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_asset_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CampaignAssetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_asset_service/client.py b/google/ads/googleads/v15/services/services/campaign_asset_service/client.py new file mode 100644 index 000000000..3426fab91 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_asset_service/client.py @@ -0,0 +1,575 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignAssetServiceTransport): + # transport is a CampaignAssetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCampaignAssetsRequest, dict, None]): + The request object. Request message for + [CampaignAssetService.MutateCampaignAssets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_asset_service.MutateCampaignAssetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignAssetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_asset_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_asset_service/transports/__init__.py new file mode 100644 index 000000000..b3abd72d8 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_asset_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignAssetServiceTransport]] +_transport_registry["grpc"] = CampaignAssetServiceGrpcTransport + +__all__ = ( + "CampaignAssetServiceTransport", + "CampaignAssetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_asset_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_asset_service/transports/base.py new file mode 100644 index 000000000..ec05ce58b --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_asset_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import campaign_asset_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CampaignAssetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_asset_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_asset_service/transports/grpc.py new file mode 100644 index 000000000..037526ef4 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_asset_service/transports/grpc.py @@ -0,0 +1,282 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import campaign_asset_service +from .base import CampaignAssetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CampaignAssetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_asset_set_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_asset_set_service/__init__.py new file mode 100644 index 000000000..b7fa09b4c --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_asset_set_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CampaignAssetSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_asset_set_service/client.py b/google/ads/googleads/v15/services/services/campaign_asset_set_service/client.py new file mode 100644 index 000000000..2671de758 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_asset_set_service/client.py @@ -0,0 +1,580 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignAssetSetServiceTransport): + # transport is a CampaignAssetSetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> campaign_asset_set_service.MutateCampaignAssetSetsResponse: + r"""Creates, updates or removes campaign asset sets. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateCampaignAssetSetsRequest, dict, None]): + The request object. Request message for + [CampaignAssetSetService.MutateCampaignAssetSets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_asset_set_service.MutateCampaignAssetSetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignAssetSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_asset_set_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_asset_set_service/transports/__init__.py new file mode 100644 index 000000000..760b275a9 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_asset_set_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignAssetSetServiceTransport]] +_transport_registry["grpc"] = CampaignAssetSetServiceGrpcTransport + +__all__ = ( + "CampaignAssetSetServiceTransport", + "CampaignAssetSetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_asset_set_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_asset_set_service/transports/base.py new file mode 100644 index 000000000..8cfd31b9f --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_asset_set_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import campaign_asset_set_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CampaignAssetSetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_asset_set_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_asset_set_service/transports/grpc.py new file mode 100644 index 000000000..c67e7ba64 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_asset_set_service/transports/grpc.py @@ -0,0 +1,276 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import campaign_asset_set_service +from .base import CampaignAssetSetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CampaignAssetSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/__init__.py new file mode 100644 index 000000000..3a5db0a67 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CampaignBidModifierServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/client.py b/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/client.py new file mode 100644 index 000000000..1fb84e6af --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/client.py @@ -0,0 +1,576 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignBidModifierServiceTransport): + # transport is a CampaignBidModifierServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCampaignBidModifiersRequest, dict, None]): + The request object. Request message for + [CampaignBidModifierService.MutateCampaignBidModifiers][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_bid_modifier_service.MutateCampaignBidModifiersRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignBidModifierServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/transports/__init__.py new file mode 100644 index 000000000..453571e80 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignBidModifierServiceTransport]] +_transport_registry["grpc"] = CampaignBidModifierServiceGrpcTransport + +__all__ = ( + "CampaignBidModifierServiceTransport", + "CampaignBidModifierServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/transports/base.py new file mode 100644 index 000000000..c3af152b0 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + campaign_bid_modifier_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CampaignBidModifierServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/transports/grpc.py new file mode 100644 index 000000000..470776b0d --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_bid_modifier_service/transports/grpc.py @@ -0,0 +1,290 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + campaign_bid_modifier_service, +) +from .base import CampaignBidModifierServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CampaignBidModifierServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_budget_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_budget_service/__init__.py new file mode 100644 index 000000000..29172a131 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_budget_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CampaignBudgetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_budget_service/client.py b/google/ads/googleads/v15/services/services/campaign_budget_service/client.py new file mode 100644 index 000000000..2476567e6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_budget_service/client.py @@ -0,0 +1,535 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignBudgetServiceTransport): + # transport is a CampaignBudgetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCampaignBudgetsRequest, dict, None]): + The request object. Request message for + [CampaignBudgetService.MutateCampaignBudgets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_budget_service.MutateCampaignBudgetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignBudgetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_budget_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_budget_service/transports/__init__.py new file mode 100644 index 000000000..ef6c0a040 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_budget_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignBudgetServiceTransport]] +_transport_registry["grpc"] = CampaignBudgetServiceGrpcTransport + +__all__ = ( + "CampaignBudgetServiceTransport", + "CampaignBudgetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_budget_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_budget_service/transports/base.py new file mode 100644 index 000000000..bb8a706e7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_budget_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import campaign_budget_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CampaignBudgetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_budget_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_budget_service/transports/grpc.py new file mode 100644 index 000000000..adc2ce571 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_budget_service/transports/grpc.py @@ -0,0 +1,285 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import campaign_budget_service +from .base import CampaignBudgetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CampaignBudgetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/__init__.py new file mode 100644 index 000000000..0ea56c3cd --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CampaignConversionGoalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/client.py b/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/client.py new file mode 100644 index 000000000..ae8315ab7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/client.py @@ -0,0 +1,565 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + campaign_conversion_goal_service, +) +from .transports.base import ( + CampaignConversionGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CampaignConversionGoalServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignConversionGoalServiceTransport): + # transport is a CampaignConversionGoalServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> campaign_conversion_goal_service.MutateCampaignConversionGoalsResponse: + r"""Creates, updates or removes campaign conversion + goals. Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateCampaignConversionGoalsRequest, dict, None]): + The request object. Request message for + [CampaignConversionGoalService.MutateCampaignConversionGoals][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_conversion_goal_service.MutateCampaignConversionGoalsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignConversionGoalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/transports/__init__.py new file mode 100644 index 000000000..9b9b3dc10 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignConversionGoalServiceTransport]] +_transport_registry["grpc"] = CampaignConversionGoalServiceGrpcTransport + +__all__ = ( + "CampaignConversionGoalServiceTransport", + "CampaignConversionGoalServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/transports/base.py new file mode 100644 index 000000000..d1c3f5617 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + campaign_conversion_goal_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CampaignConversionGoalServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/transports/grpc.py new file mode 100644 index 000000000..1a89b27bf --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_conversion_goal_service/transports/grpc.py @@ -0,0 +1,281 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + campaign_conversion_goal_service, +) +from .base import CampaignConversionGoalServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CampaignConversionGoalServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_criterion_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_criterion_service/__init__.py new file mode 100644 index 000000000..a50cf27ff --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_criterion_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CampaignCriterionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_criterion_service/client.py b/google/ads/googleads/v15/services/services/campaign_criterion_service/client.py new file mode 100644 index 000000000..d20bdae05 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_criterion_service/client.py @@ -0,0 +1,625 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignCriterionServiceTransport): + # transport is a CampaignCriterionServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCampaignCriteriaRequest, dict, None]): + The request object. Request message for + [CampaignCriterionService.MutateCampaignCriteria][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_criterion_service.MutateCampaignCriteriaRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignCriterionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_criterion_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_criterion_service/transports/__init__.py new file mode 100644 index 000000000..cf4599463 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_criterion_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignCriterionServiceTransport]] +_transport_registry["grpc"] = CampaignCriterionServiceGrpcTransport + +__all__ = ( + "CampaignCriterionServiceTransport", + "CampaignCriterionServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_criterion_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_criterion_service/transports/base.py new file mode 100644 index 000000000..90b16baed --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_criterion_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import campaign_criterion_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CampaignCriterionServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_criterion_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_criterion_service/transports/grpc.py new file mode 100644 index 000000000..13e13db02 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_criterion_service/transports/grpc.py @@ -0,0 +1,290 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import campaign_criterion_service +from .base import CampaignCriterionServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CampaignCriterionServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_customizer_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_customizer_service/__init__.py new file mode 100644 index 000000000..6adf91126 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_customizer_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CampaignCustomizerServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_customizer_service/client.py b/google/ads/googleads/v15/services/services/campaign_customizer_service/client.py new file mode 100644 index 000000000..166b2aa9d --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_customizer_service/client.py @@ -0,0 +1,584 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignCustomizerServiceTransport): + # transport is a CampaignCustomizerServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> campaign_customizer_service.MutateCampaignCustomizersResponse: + r"""Creates, updates or removes campaign customizers. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateCampaignCustomizersRequest, dict, None]): + The request object. Request message for + [CampaignCustomizerService.MutateCampaignCustomizers][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_customizer_service.MutateCampaignCustomizersRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignCustomizerServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_customizer_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_customizer_service/transports/__init__.py new file mode 100644 index 000000000..8eee1d5d3 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_customizer_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignCustomizerServiceTransport]] +_transport_registry["grpc"] = CampaignCustomizerServiceGrpcTransport + +__all__ = ( + "CampaignCustomizerServiceTransport", + "CampaignCustomizerServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_customizer_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_customizer_service/transports/base.py new file mode 100644 index 000000000..911180302 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_customizer_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import campaign_customizer_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CampaignCustomizerServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_customizer_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_customizer_service/transports/grpc.py new file mode 100644 index 000000000..96adb6460 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_customizer_service/transports/grpc.py @@ -0,0 +1,278 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import campaign_customizer_service +from .base import CampaignCustomizerServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CampaignCustomizerServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_draft_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_draft_service/__init__.py new file mode 100644 index 000000000..4e71171a9 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_draft_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CampaignDraftServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_draft_service/client.py b/google/ads/googleads/v15/services/services/campaign_draft_service/client.py new file mode 100644 index 000000000..807f19bad --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_draft_service/client.py @@ -0,0 +1,787 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.services.campaign_draft_service import ( + pagers, +) +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignDraftServiceTransport): + # transport is a CampaignDraftServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCampaignDraftsRequest, dict, None]): + The request object. Request message for + [CampaignDraftService.MutateCampaignDrafts][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_draft_service.MutateCampaignDraftsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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 [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.v15.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.v15.services.types.PromoteCampaignDraftRequest, dict, None]): + The request object. Request message for + [CampaignDraftService.PromoteCampaignDraft][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.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. + has_flattened_params = any([campaign_draft]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_draft_service.PromoteCampaignDraftRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.ListCampaignDraftAsyncErrorsRequest, dict, None]): + The request object. Request message for + [CampaignDraftService.ListCampaignDraftAsyncErrors][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.services.campaign_draft_service.pagers.ListCampaignDraftAsyncErrorsPager: + Response message for + [CampaignDraftService.ListCampaignDraftAsyncErrors][google.ads.googleads.v15.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. + has_flattened_params = any([resource_name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_draft_service.ListCampaignDraftAsyncErrorsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignDraftServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_draft_service/pagers.py b/google/ads/googleads/v15/services/services/campaign_draft_service/pagers.py new file mode 100644 index 000000000..3bea0cede --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_draft_service/pagers.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Any, Callable, Iterable, Iterator, Sequence, Tuple + +from google.ads.googleads.v15.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.v15.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.v15.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, + metadata: Sequence[Tuple[str, str]] = (), + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (:class:`google.ads.googleads.v15.services.types.ListCampaignDraftAsyncErrorsRequest`): + The initial request object. + response (:class:`google.ads.googleads.v15.services.types.ListCampaignDraftAsyncErrorsResponse`): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = ( + campaign_draft_service.ListCampaignDraftAsyncErrorsRequest(request) + ) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages( + self, + ) -> Iterable[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, 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) diff --git a/google/ads/googleads/v15/services/services/campaign_draft_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_draft_service/transports/__init__.py new file mode 100644 index 000000000..66508c21b --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_draft_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignDraftServiceTransport]] +_transport_registry["grpc"] = CampaignDraftServiceGrpcTransport + +__all__ = ( + "CampaignDraftServiceTransport", + "CampaignDraftServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_draft_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_draft_service/transports/base.py new file mode 100644 index 000000000..88aa9ca7c --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_draft_service/transports/base.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import campaign_draft_service +from google.longrunning import operations_pb2 # type: ignore + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CampaignDraftServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_draft_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_draft_service/transports/grpc.py new file mode 100644 index 000000000..95e311751 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_draft_service/transports/grpc.py @@ -0,0 +1,384 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import campaign_draft_service +from google.longrunning import operations_pb2 # type: ignore +from .base import CampaignDraftServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client: Optional[operations_v1.OperationsClient] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def operations_client(self) -> operations_v1.OperationsClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsClient( + self.grpc_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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 [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.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CampaignDraftServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_extension_setting_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_extension_setting_service/__init__.py new file mode 100644 index 000000000..ebaf27137 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_extension_setting_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 CampaignExtensionSettingServiceClient + +__all__ = ("CampaignExtensionSettingServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_extension_setting_service/client.py b/google/ads/googleads/v15/services/services/campaign_extension_setting_service/client.py new file mode 100644 index 000000000..b7b67f451 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_extension_setting_service/client.py @@ -0,0 +1,599 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + campaign_extension_setting_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CampaignExtensionSettingServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CampaignExtensionSettingServiceGrpcTransport + + +class CampaignExtensionSettingServiceClientMeta(type): + """Metaclass for the CampaignExtensionSettingService 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[CampaignExtensionSettingServiceTransport]] + _transport_registry["grpc"] = CampaignExtensionSettingServiceGrpcTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignExtensionSettingServiceTransport]: + """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 CampaignExtensionSettingServiceClient( + metaclass=CampaignExtensionSettingServiceClientMeta +): + """Service to manage campaign extension 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + CampaignExtensionSettingServiceClient: 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: + CampaignExtensionSettingServiceClient: 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) -> CampaignExtensionSettingServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignExtensionSettingServiceTransport: The transport used by the client + instance. + """ + return self._transport + + def __enter__(self) -> "CampaignExtensionSettingServiceClient": + 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() + + @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_extension_setting_path( + customer_id: str, + campaign_id: str, + extension_type: str, + ) -> str: + """Returns a fully-qualified campaign_extension_setting string.""" + return "customers/{customer_id}/campaignExtensionSettings/{campaign_id}~{extension_type}".format( + customer_id=customer_id, + campaign_id=campaign_id, + extension_type=extension_type, + ) + + @staticmethod + def parse_campaign_extension_setting_path(path: str) -> Dict[str, str]: + """Parses a campaign_extension_setting path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignExtensionSettings/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def extension_feed_item_path( + customer_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified extension_feed_item string.""" + return ( + "customers/{customer_id}/extensionFeedItems/{feed_item_id}".format( + customer_id=customer_id, + feed_item_id=feed_item_id, + ) + ) + + @staticmethod + def parse_extension_feed_item_path(path: str) -> Dict[str, str]: + """Parses a extension_feed_item path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/extensionFeedItems/(?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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, CampaignExtensionSettingServiceTransport] + ] = 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 extension 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, CampaignExtensionSettingServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignExtensionSettingServiceTransport): + # transport is a CampaignExtensionSettingServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def mutate_campaign_extension_settings( + self, + request: Optional[ + Union[ + campaign_extension_setting_service.MutateCampaignExtensionSettingsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + campaign_extension_setting_service.CampaignExtensionSettingOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> campaign_extension_setting_service.MutateCampaignExtensionSettingsResponse: + r"""Creates, updates, or removes campaign extension settings. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `CriterionError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `ExtensionSettingError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateCampaignExtensionSettingsRequest, dict, None]): + The request object. Request message for + [CampaignExtensionSettingService.MutateCampaignExtensionSettings][google.ads.googleads.v15.services.CampaignExtensionSettingService.MutateCampaignExtensionSettings]. + customer_id (str): + Required. The ID of the customer + whose campaign extension 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.v15.services.types.CampaignExtensionSettingOperation]): + Required. The list of operations to + perform on individual campaign extension + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateCampaignExtensionSettingsResponse: + Response message for a campaign + extension setting 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_extension_setting_service.MutateCampaignExtensionSettingsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, + campaign_extension_setting_service.MutateCampaignExtensionSettingsRequest, + ): + request = campaign_extension_setting_service.MutateCampaignExtensionSettingsRequest( + request + ) + # 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_extension_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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignExtensionSettingServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_extension_setting_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_extension_setting_service/transports/__init__.py new file mode 100644 index 000000000..b59b9b792 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_extension_setting_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 CampaignExtensionSettingServiceTransport +from .grpc import CampaignExtensionSettingServiceGrpcTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignExtensionSettingServiceTransport]] +_transport_registry["grpc"] = CampaignExtensionSettingServiceGrpcTransport + +__all__ = ( + "CampaignExtensionSettingServiceTransport", + "CampaignExtensionSettingServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_extension_setting_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_extension_setting_service/transports/base.py new file mode 100644 index 000000000..70b6d5d43 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_extension_setting_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + campaign_extension_setting_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class CampaignExtensionSettingServiceTransport(abc.ABC): + """Abstract transport class for CampaignExtensionSettingService.""" + + 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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_extension_settings: gapic_v1.method.wrap_method( + self.mutate_campaign_extension_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 mutate_campaign_extension_settings( + self, + ) -> Callable[ + [ + campaign_extension_setting_service.MutateCampaignExtensionSettingsRequest + ], + Union[ + campaign_extension_setting_service.MutateCampaignExtensionSettingsResponse, + Awaitable[ + campaign_extension_setting_service.MutateCampaignExtensionSettingsResponse + ], + ], + ]: + raise NotImplementedError() + + +__all__ = ("CampaignExtensionSettingServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_extension_setting_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_extension_setting_service/transports/grpc.py new file mode 100644 index 000000000..524540e49 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_extension_setting_service/transports/grpc.py @@ -0,0 +1,296 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + campaign_extension_setting_service, +) +from .base import CampaignExtensionSettingServiceTransport, DEFAULT_CLIENT_INFO + + +class CampaignExtensionSettingServiceGrpcTransport( + CampaignExtensionSettingServiceTransport +): + """gRPC backend transport for CampaignExtensionSettingService. + + Service to manage campaign extension 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def mutate_campaign_extension_settings( + self, + ) -> Callable[ + [ + campaign_extension_setting_service.MutateCampaignExtensionSettingsRequest + ], + campaign_extension_setting_service.MutateCampaignExtensionSettingsResponse, + ]: + r"""Return a callable for the mutate campaign extension + settings method over gRPC. + + Creates, updates, or removes campaign extension settings. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `CriterionError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `ExtensionSettingError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateCampaignExtensionSettingsRequest], + ~.MutateCampaignExtensionSettingsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_extension_settings" not in self._stubs: + self._stubs[ + "mutate_campaign_extension_settings" + ] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.CampaignExtensionSettingService/MutateCampaignExtensionSettings", + request_serializer=campaign_extension_setting_service.MutateCampaignExtensionSettingsRequest.serialize, + response_deserializer=campaign_extension_setting_service.MutateCampaignExtensionSettingsResponse.deserialize, + ) + return self._stubs["mutate_campaign_extension_settings"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("CampaignExtensionSettingServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_feed_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_feed_service/__init__.py new file mode 100644 index 000000000..1a9d0d085 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_feed_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 CampaignFeedServiceClient + +__all__ = ("CampaignFeedServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_feed_service/client.py b/google/ads/googleads/v15/services/services/campaign_feed_service/client.py new file mode 100644 index 000000000..d6f07e392 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_feed_service/client.py @@ -0,0 +1,575 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import campaign_feed_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CampaignFeedServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CampaignFeedServiceGrpcTransport + + +class CampaignFeedServiceClientMeta(type): + """Metaclass for the CampaignFeedService 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[CampaignFeedServiceTransport]] + _transport_registry["grpc"] = CampaignFeedServiceGrpcTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CampaignFeedServiceTransport]: + """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 CampaignFeedServiceClient(metaclass=CampaignFeedServiceClientMeta): + """Service to manage campaign feeds.""" + + @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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + CampaignFeedServiceClient: 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: + CampaignFeedServiceClient: 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) -> CampaignFeedServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CampaignFeedServiceTransport: The transport used by the client + instance. + """ + return self._transport + + def __enter__(self) -> "CampaignFeedServiceClient": + 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() + + @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_feed_path( + customer_id: str, + campaign_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified campaign_feed string.""" + return "customers/{customer_id}/campaignFeeds/{campaign_id}~{feed_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_campaign_feed_path(path: str) -> Dict[str, str]: + """Parses a campaign_feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignFeeds/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_path( + customer_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified feed string.""" + return "customers/{customer_id}/feeds/{feed_id}".format( + customer_id=customer_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_feed_path(path: str) -> Dict[str, str]: + """Parses a feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feeds/(?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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, CampaignFeedServiceTransport]] = 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 feed 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, CampaignFeedServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignFeedServiceTransport): + # transport is a CampaignFeedServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def mutate_campaign_feeds( + self, + request: Optional[ + Union[campaign_feed_service.MutateCampaignFeedsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[campaign_feed_service.CampaignFeedOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> campaign_feed_service.MutateCampaignFeedsResponse: + r"""Creates, updates, or removes campaign feeds. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignFeedError <>`__ + `CollectionSizeError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FunctionError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `MutateError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateCampaignFeedsRequest, dict, None]): + The request object. Request message for + [CampaignFeedService.MutateCampaignFeeds][google.ads.googleads.v15.services.CampaignFeedService.MutateCampaignFeeds]. + customer_id (str): + Required. The ID of the customer + whose campaign feeds 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.v15.services.types.CampaignFeedOperation]): + Required. The list of operations to + perform on individual campaign feeds. + + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateCampaignFeedsResponse: + Response message for a campaign feed + 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_feed_service.MutateCampaignFeedsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, campaign_feed_service.MutateCampaignFeedsRequest + ): + request = campaign_feed_service.MutateCampaignFeedsRequest(request) + # 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_feeds + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignFeedServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_feed_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_feed_service/transports/__init__.py new file mode 100644 index 000000000..834872dbb --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_feed_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 CampaignFeedServiceTransport +from .grpc import CampaignFeedServiceGrpcTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignFeedServiceTransport]] +_transport_registry["grpc"] = CampaignFeedServiceGrpcTransport + +__all__ = ( + "CampaignFeedServiceTransport", + "CampaignFeedServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_feed_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_feed_service/transports/base.py new file mode 100644 index 000000000..c1047330d --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_feed_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import campaign_feed_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class CampaignFeedServiceTransport(abc.ABC): + """Abstract transport class for CampaignFeedService.""" + + 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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_campaign_feeds: gapic_v1.method.wrap_method( + self.mutate_campaign_feeds, + 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_feeds( + self, + ) -> Callable[ + [campaign_feed_service.MutateCampaignFeedsRequest], + Union[ + campaign_feed_service.MutateCampaignFeedsResponse, + Awaitable[campaign_feed_service.MutateCampaignFeedsResponse], + ], + ]: + raise NotImplementedError() + + +__all__ = ("CampaignFeedServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_feed_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_feed_service/transports/grpc.py new file mode 100644 index 000000000..021e65635 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_feed_service/transports/grpc.py @@ -0,0 +1,287 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import campaign_feed_service +from .base import CampaignFeedServiceTransport, DEFAULT_CLIENT_INFO + + +class CampaignFeedServiceGrpcTransport(CampaignFeedServiceTransport): + """gRPC backend transport for CampaignFeedService. + + Service to manage campaign feeds. + + This 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def mutate_campaign_feeds( + self, + ) -> Callable[ + [campaign_feed_service.MutateCampaignFeedsRequest], + campaign_feed_service.MutateCampaignFeedsResponse, + ]: + r"""Return a callable for the mutate campaign feeds method over gRPC. + + Creates, updates, or removes campaign feeds. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CampaignFeedError <>`__ + `CollectionSizeError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FunctionError <>`__ + `FunctionParsingError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `MutateError <>`__ `NotEmptyError <>`__ + `NullError <>`__ `OperationAccessDeniedError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateCampaignFeedsRequest], + ~.MutateCampaignFeedsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_feeds" not in self._stubs: + self._stubs[ + "mutate_campaign_feeds" + ] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.CampaignFeedService/MutateCampaignFeeds", + request_serializer=campaign_feed_service.MutateCampaignFeedsRequest.serialize, + response_deserializer=campaign_feed_service.MutateCampaignFeedsResponse.deserialize, + ) + return self._stubs["mutate_campaign_feeds"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("CampaignFeedServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_group_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_group_service/__init__.py new file mode 100644 index 000000000..1242adb2d --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_group_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CampaignGroupServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_group_service/client.py b/google/ads/googleads/v15/services/services/campaign_group_service/client.py new file mode 100644 index 000000000..e9e51d9a0 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_group_service/client.py @@ -0,0 +1,528 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignGroupServiceTransport): + # transport is a CampaignGroupServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> campaign_group_service.MutateCampaignGroupsResponse: + r"""Creates, updates, or removes campaign groups. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateCampaignGroupsRequest, dict, None]): + The request object. Request message for + [CampaignGroupService.MutateCampaignGroups][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_group_service.MutateCampaignGroupsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignGroupServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_group_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_group_service/transports/__init__.py new file mode 100644 index 000000000..ce0f1379d --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_group_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignGroupServiceTransport]] +_transport_registry["grpc"] = CampaignGroupServiceGrpcTransport + +__all__ = ( + "CampaignGroupServiceTransport", + "CampaignGroupServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_group_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_group_service/transports/base.py new file mode 100644 index 000000000..4454d9bec --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_group_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import campaign_group_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CampaignGroupServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_group_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_group_service/transports/grpc.py new file mode 100644 index 000000000..914e68e7b --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_group_service/transports/grpc.py @@ -0,0 +1,276 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import campaign_group_service +from .base import CampaignGroupServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CampaignGroupServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_label_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_label_service/__init__.py new file mode 100644 index 000000000..139ea217d --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_label_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CampaignLabelServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_label_service/client.py b/google/ads/googleads/v15/services/services/campaign_label_service/client.py new file mode 100644 index 000000000..11b24702f --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_label_service/client.py @@ -0,0 +1,573 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignLabelServiceTransport): + # transport is a CampaignLabelServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCampaignLabelsRequest, dict, None]): + The request object. Request message for + [CampaignLabelService.MutateCampaignLabels][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_label_service.MutateCampaignLabelsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignLabelServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_label_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_label_service/transports/__init__.py new file mode 100644 index 000000000..ac170d8cb --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_label_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignLabelServiceTransport]] +_transport_registry["grpc"] = CampaignLabelServiceGrpcTransport + +__all__ = ( + "CampaignLabelServiceTransport", + "CampaignLabelServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_label_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_label_service/transports/base.py new file mode 100644 index 000000000..eca5f4a16 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_label_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import campaign_label_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CampaignLabelServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_label_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_label_service/transports/grpc.py new file mode 100644 index 000000000..a11695b08 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_label_service/transports/grpc.py @@ -0,0 +1,282 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import campaign_label_service +from .base import CampaignLabelServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CampaignLabelServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/__init__.py new file mode 100644 index 000000000..4b81ad062 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CampaignLifecycleGoalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/client.py b/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/client.py new file mode 100644 index 000000000..f81622de8 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/client.py @@ -0,0 +1,552 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + campaign_lifecycle_goal_service, +) +from .transports.base import ( + CampaignLifecycleGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CampaignLifecycleGoalServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignLifecycleGoalServiceTransport): + # transport is a CampaignLifecycleGoalServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.ConfigureCampaignLifecycleGoalsRequest, dict, None]): + The request object. Request message for + [CampaignLifecycleService.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.ConfigureCampaignLifecycleGoalsResponse: + Response message for + [CampaignLifecycleService.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. + has_flattened_params = any([customer_id, operation]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_lifecycle_goal_service.ConfigureCampaignLifecycleGoalsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignLifecycleGoalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/transports/__init__.py new file mode 100644 index 000000000..0ca14ff5b --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignLifecycleGoalServiceTransport]] +_transport_registry["grpc"] = CampaignLifecycleGoalServiceGrpcTransport + +__all__ = ( + "CampaignLifecycleGoalServiceTransport", + "CampaignLifecycleGoalServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/transports/base.py new file mode 100644 index 000000000..2b05bab22 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + campaign_lifecycle_goal_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CampaignLifecycleGoalServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/transports/grpc.py new file mode 100644 index 000000000..ad6d2f9ac --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_lifecycle_goal_service/transports/grpc.py @@ -0,0 +1,287 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + campaign_lifecycle_goal_service, +) +from .base import CampaignLifecycleGoalServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CampaignLifecycleGoalServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_service/__init__.py new file mode 100644 index 000000000..a82480a3c --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CampaignServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_service/client.py b/google/ads/googleads/v15/services/services/campaign_service/client.py new file mode 100644 index 000000000..aaa7a6606 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_service/client.py @@ -0,0 +1,697 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 feed_path( + customer_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified feed string.""" + return "customers/{customer_id}/feeds/{feed_id}".format( + customer_id=customer_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_feed_path(path: str) -> Dict[str, str]: + """Parses a feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feeds/(?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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignServiceTransport): + # transport is a CampaignServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCampaignsRequest, dict, None]): + The request object. Request message for + [CampaignService.MutateCampaigns][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_service.MutateCampaignsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_service/transports/__init__.py new file mode 100644 index 000000000..05613599f --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignServiceTransport]] +_transport_registry["grpc"] = CampaignServiceGrpcTransport + +__all__ = ( + "CampaignServiceTransport", + "CampaignServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_service/transports/base.py new file mode 100644 index 000000000..b57cd1ea3 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import campaign_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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, + ), + } + + 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() + + +__all__ = ("CampaignServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_service/transports/grpc.py new file mode 100644 index 000000000..be4dee277 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_service/transports/grpc.py @@ -0,0 +1,291 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import campaign_service +from .base import CampaignServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.CampaignService/MutateCampaigns", + request_serializer=campaign_service.MutateCampaignsRequest.serialize, + response_deserializer=campaign_service.MutateCampaignsResponse.deserialize, + ) + return self._stubs["mutate_campaigns"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("CampaignServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_shared_set_service/__init__.py b/google/ads/googleads/v15/services/services/campaign_shared_set_service/__init__.py new file mode 100644 index 000000000..37179dc0a --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_shared_set_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CampaignSharedSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_shared_set_service/client.py b/google/ads/googleads/v15/services/services/campaign_shared_set_service/client.py new file mode 100644 index 000000000..248f4879d --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_shared_set_service/client.py @@ -0,0 +1,593 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CampaignSharedSetServiceTransport): + # transport is a CampaignSharedSetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCampaignSharedSetsRequest, dict, None]): + The request object. Request message for + [CampaignSharedSetService.MutateCampaignSharedSets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a campaign_shared_set_service.MutateCampaignSharedSetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CampaignSharedSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/campaign_shared_set_service/transports/__init__.py b/google/ads/googleads/v15/services/services/campaign_shared_set_service/transports/__init__.py new file mode 100644 index 000000000..efb3695ae --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_shared_set_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CampaignSharedSetServiceTransport]] +_transport_registry["grpc"] = CampaignSharedSetServiceGrpcTransport + +__all__ = ( + "CampaignSharedSetServiceTransport", + "CampaignSharedSetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/campaign_shared_set_service/transports/base.py b/google/ads/googleads/v15/services/services/campaign_shared_set_service/transports/base.py new file mode 100644 index 000000000..6d15b2d91 --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_shared_set_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import campaign_shared_set_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CampaignSharedSetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/campaign_shared_set_service/transports/grpc.py b/google/ads/googleads/v15/services/services/campaign_shared_set_service/transports/grpc.py new file mode 100644 index 000000000..6762291bf --- /dev/null +++ b/google/ads/googleads/v15/services/services/campaign_shared_set_service/transports/grpc.py @@ -0,0 +1,286 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import campaign_shared_set_service +from .base import CampaignSharedSetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CampaignSharedSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_action_service/__init__.py b/google/ads/googleads/v15/services/services/conversion_action_service/__init__.py new file mode 100644 index 000000000..bc563dd77 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_action_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("ConversionActionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_action_service/client.py b/google/ads/googleads/v15/services/services/conversion_action_service/client.py new file mode 100644 index 000000000..bb15069b2 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_action_service/client.py @@ -0,0 +1,559 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ConversionActionServiceTransport): + # transport is a ConversionActionServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateConversionActionsRequest, dict, None]): + The request object. Request message for + [ConversionActionService.MutateConversionActions][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateConversionActionsResponse: + Response message for + [ConversionActionService.MutateConversionActions][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversion_action_service.MutateConversionActionsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ConversionActionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_action_service/transports/__init__.py b/google/ads/googleads/v15/services/services/conversion_action_service/transports/__init__.py new file mode 100644 index 000000000..32d21c54b --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_action_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionActionServiceTransport]] +_transport_registry["grpc"] = ConversionActionServiceGrpcTransport + +__all__ = ( + "ConversionActionServiceTransport", + "ConversionActionServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/conversion_action_service/transports/base.py b/google/ads/googleads/v15/services/services/conversion_action_service/transports/base.py new file mode 100644 index 000000000..2d0ba6915 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_action_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import conversion_action_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("ConversionActionServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_action_service/transports/grpc.py b/google/ads/googleads/v15/services/services/conversion_action_service/transports/grpc.py new file mode 100644 index 000000000..2b9edea80 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_action_service/transports/grpc.py @@ -0,0 +1,284 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import conversion_action_service +from .base import ConversionActionServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("ConversionActionServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/__init__.py b/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/__init__.py new file mode 100644 index 000000000..0b7054672 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("ConversionAdjustmentUploadServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/client.py b/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/client.py new file mode 100644 index 000000000..fad259514 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/client.py @@ -0,0 +1,545 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ConversionAdjustmentUploadServiceTransport): + # transport is a ConversionAdjustmentUploadServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.UploadConversionAdjustmentsRequest, dict, None]): + The request object. Request message for + [ConversionAdjustmentUploadService.UploadConversionAdjustments][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.UploadConversionAdjustmentsResponse: + Response message for + [ConversionAdjustmentUploadService.UploadConversionAdjustments][google.ads.googleads.v15.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. + has_flattened_params = any( + [customer_id, conversion_adjustments, partial_failure] + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversion_adjustment_upload_service.UploadConversionAdjustmentsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ConversionAdjustmentUploadServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/transports/__init__.py b/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/transports/__init__.py new file mode 100644 index 000000000..79baf0839 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionAdjustmentUploadServiceTransport]] +_transport_registry["grpc"] = ConversionAdjustmentUploadServiceGrpcTransport + +__all__ = ( + "ConversionAdjustmentUploadServiceTransport", + "ConversionAdjustmentUploadServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/transports/base.py b/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/transports/base.py new file mode 100644 index 000000000..a5d0a3fe1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + conversion_adjustment_upload_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("ConversionAdjustmentUploadServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/transports/grpc.py b/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/transports/grpc.py new file mode 100644 index 000000000..fd1fe5465 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_adjustment_upload_service/transports/grpc.py @@ -0,0 +1,289 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + conversion_adjustment_upload_service, +) +from .base import ( + ConversionAdjustmentUploadServiceTransport, + DEFAULT_CLIENT_INFO, +) + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("ConversionAdjustmentUploadServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_custom_variable_service/__init__.py b/google/ads/googleads/v15/services/services/conversion_custom_variable_service/__init__.py new file mode 100644 index 000000000..7e6fb26f4 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_custom_variable_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("ConversionCustomVariableServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_custom_variable_service/client.py b/google/ads/googleads/v15/services/services/conversion_custom_variable_service/client.py new file mode 100644 index 000000000..0b887d008 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_custom_variable_service/client.py @@ -0,0 +1,562 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ConversionCustomVariableServiceTransport): + # transport is a ConversionCustomVariableServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateConversionCustomVariablesRequest, dict, None]): + The request object. Request message for + [ConversionCustomVariableService.MutateConversionCustomVariables][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateConversionCustomVariablesResponse: + Response message for + [ConversionCustomVariableService.MutateConversionCustomVariables][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversion_custom_variable_service.MutateConversionCustomVariablesRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ConversionCustomVariableServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_custom_variable_service/transports/__init__.py b/google/ads/googleads/v15/services/services/conversion_custom_variable_service/transports/__init__.py new file mode 100644 index 000000000..be8e7db16 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_custom_variable_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionCustomVariableServiceTransport]] +_transport_registry["grpc"] = ConversionCustomVariableServiceGrpcTransport + +__all__ = ( + "ConversionCustomVariableServiceTransport", + "ConversionCustomVariableServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/conversion_custom_variable_service/transports/base.py b/google/ads/googleads/v15/services/services/conversion_custom_variable_service/transports/base.py new file mode 100644 index 000000000..0db459d4e --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_custom_variable_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + conversion_custom_variable_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("ConversionCustomVariableServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_custom_variable_service/transports/grpc.py b/google/ads/googleads/v15/services/services/conversion_custom_variable_service/transports/grpc.py new file mode 100644 index 000000000..7b29d3676 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_custom_variable_service/transports/grpc.py @@ -0,0 +1,288 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + conversion_custom_variable_service, +) +from .base import ConversionCustomVariableServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("ConversionCustomVariableServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/__init__.py b/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/__init__.py new file mode 100644 index 000000000..4607b62cf --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("ConversionGoalCampaignConfigServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/client.py b/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/client.py new file mode 100644 index 000000000..ae13f9b14 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/client.py @@ -0,0 +1,583 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + conversion_goal_campaign_config_service, +) +from .transports.base import ( + ConversionGoalCampaignConfigServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ConversionGoalCampaignConfigServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ConversionGoalCampaignConfigServiceTransport): + # transport is a ConversionGoalCampaignConfigServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateConversionGoalCampaignConfigsRequest, dict, None]): + The request object. Request message for + [ConversionGoalCampaignConfigService.MutateConversionGoalCampaignConfigs][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversion_goal_campaign_config_service.MutateConversionGoalCampaignConfigsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ConversionGoalCampaignConfigServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/transports/__init__.py b/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/transports/__init__.py new file mode 100644 index 000000000..3c97bd854 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionGoalCampaignConfigServiceTransport]] +_transport_registry["grpc"] = ConversionGoalCampaignConfigServiceGrpcTransport + +__all__ = ( + "ConversionGoalCampaignConfigServiceTransport", + "ConversionGoalCampaignConfigServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/transports/base.py b/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/transports/base.py new file mode 100644 index 000000000..1254ae9a5 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + conversion_goal_campaign_config_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("ConversionGoalCampaignConfigServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/transports/grpc.py b/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/transports/grpc.py new file mode 100644 index 000000000..6f60fba20 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_goal_campaign_config_service/transports/grpc.py @@ -0,0 +1,286 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + conversion_goal_campaign_config_service, +) +from .base import ( + ConversionGoalCampaignConfigServiceTransport, + DEFAULT_CLIENT_INFO, +) + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("ConversionGoalCampaignConfigServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_upload_service/__init__.py b/google/ads/googleads/v15/services/services/conversion_upload_service/__init__.py new file mode 100644 index 000000000..ce31f7ec4 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_upload_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("ConversionUploadServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_upload_service/client.py b/google/ads/googleads/v15/services/services/conversion_upload_service/client.py new file mode 100644 index 000000000..e309d2525 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_upload_service/client.py @@ -0,0 +1,677 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ConversionUploadServiceTransport): + # transport is a ConversionUploadServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.UploadClickConversionsRequest, dict, None]): + The request object. Request message for + [ConversionUploadService.UploadClickConversions][google.ads.googleads.v15.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.v15.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 + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.UploadClickConversionsResponse: + Response message for + [ConversionUploadService.UploadClickConversions][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, conversions, partial_failure]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversion_upload_service.UploadClickConversionsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.UploadCallConversionsRequest, dict, None]): + The request object. Request message for + [ConversionUploadService.UploadCallConversions][google.ads.googleads.v15.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.v15.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 + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.UploadCallConversionsResponse: + Response message for + [ConversionUploadService.UploadCallConversions][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, conversions, partial_failure]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversion_upload_service.UploadCallConversionsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ConversionUploadServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_upload_service/transports/__init__.py b/google/ads/googleads/v15/services/services/conversion_upload_service/transports/__init__.py new file mode 100644 index 000000000..86af1e616 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_upload_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionUploadServiceTransport]] +_transport_registry["grpc"] = ConversionUploadServiceGrpcTransport + +__all__ = ( + "ConversionUploadServiceTransport", + "ConversionUploadServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/conversion_upload_service/transports/base.py b/google/ads/googleads/v15/services/services/conversion_upload_service/transports/base.py new file mode 100644 index 000000000..b1914a537 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_upload_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import conversion_upload_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("ConversionUploadServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_upload_service/transports/grpc.py b/google/ads/googleads/v15/services/services/conversion_upload_service/transports/grpc.py new file mode 100644 index 000000000..2c0646359 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_upload_service/transports/grpc.py @@ -0,0 +1,316 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import conversion_upload_service +from .base import ConversionUploadServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("ConversionUploadServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_value_rule_service/__init__.py b/google/ads/googleads/v15/services/services/conversion_value_rule_service/__init__.py new file mode 100644 index 000000000..e1b48e51d --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_value_rule_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("ConversionValueRuleServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_value_rule_service/client.py b/google/ads/googleads/v15/services/services/conversion_value_rule_service/client.py new file mode 100644 index 000000000..d3c77c386 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_value_rule_service/client.py @@ -0,0 +1,616 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ConversionValueRuleServiceTransport): + # transport is a ConversionValueRuleServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> conversion_value_rule_service.MutateConversionValueRulesResponse: + r"""Creates, updates, or removes conversion value rules. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateConversionValueRulesRequest, dict, None]): + The request object. Request message for + [ConversionValueRuleService.MutateConversionValueRules][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateConversionValueRulesResponse: + Response message for + [ConversionValueRuleService.MutateConversionValueRules][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversion_value_rule_service.MutateConversionValueRulesRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ConversionValueRuleServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_value_rule_service/transports/__init__.py b/google/ads/googleads/v15/services/services/conversion_value_rule_service/transports/__init__.py new file mode 100644 index 000000000..cfb6eaabd --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_value_rule_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionValueRuleServiceTransport]] +_transport_registry["grpc"] = ConversionValueRuleServiceGrpcTransport + +__all__ = ( + "ConversionValueRuleServiceTransport", + "ConversionValueRuleServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/conversion_value_rule_service/transports/base.py b/google/ads/googleads/v15/services/services/conversion_value_rule_service/transports/base.py new file mode 100644 index 000000000..034d0249c --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_value_rule_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + conversion_value_rule_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("ConversionValueRuleServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_value_rule_service/transports/grpc.py b/google/ads/googleads/v15/services/services/conversion_value_rule_service/transports/grpc.py new file mode 100644 index 000000000..ae6e37b39 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_value_rule_service/transports/grpc.py @@ -0,0 +1,280 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + conversion_value_rule_service, +) +from .base import ConversionValueRuleServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("ConversionValueRuleServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/__init__.py b/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/__init__.py new file mode 100644 index 000000000..b698cf653 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("ConversionValueRuleSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/client.py b/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/client.py new file mode 100644 index 000000000..b7eee124d --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/client.py @@ -0,0 +1,597 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ConversionValueRuleSetServiceTransport): + # transport is a ConversionValueRuleSetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateConversionValueRuleSetsRequest, dict, None]): + The request object. Request message for + [ConversionValueRuleSetService.MutateConversionValueRuleSets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateConversionValueRuleSetsResponse: + Response message for + [ConversionValueRuleSetService.MutateConversionValueRuleSets][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversion_value_rule_set_service.MutateConversionValueRuleSetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ConversionValueRuleSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/transports/__init__.py b/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/transports/__init__.py new file mode 100644 index 000000000..78c7f003b --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ConversionValueRuleSetServiceTransport]] +_transport_registry["grpc"] = ConversionValueRuleSetServiceGrpcTransport + +__all__ = ( + "ConversionValueRuleSetServiceTransport", + "ConversionValueRuleSetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/transports/base.py b/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/transports/base.py new file mode 100644 index 000000000..be2cb5dbb --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + conversion_value_rule_set_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("ConversionValueRuleSetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/transports/grpc.py b/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/transports/grpc.py new file mode 100644 index 000000000..dbc5baa40 --- /dev/null +++ b/google/ads/googleads/v15/services/services/conversion_value_rule_set_service/transports/grpc.py @@ -0,0 +1,283 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + conversion_value_rule_set_service, +) +from .base import ConversionValueRuleSetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("ConversionValueRuleSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/custom_audience_service/__init__.py b/google/ads/googleads/v15/services/services/custom_audience_service/__init__.py new file mode 100644 index 000000000..e92dd24b1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_audience_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomAudienceServiceClient",) diff --git a/google/ads/googleads/v15/services/services/custom_audience_service/client.py b/google/ads/googleads/v15/services/services/custom_audience_service/client.py new file mode 100644 index 000000000..b11cdce70 --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_audience_service/client.py @@ -0,0 +1,533 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import custom_audience_service +from .transports.base import CustomAudienceServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CustomAudienceServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomAudienceServiceTransport): + # transport is a CustomAudienceServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCustomAudiencesRequest, dict, None]): + The request object. Request message for + [CustomAudienceService.MutateCustomAudiences][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a custom_audience_service.MutateCustomAudiencesRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomAudienceServiceClient",) diff --git a/google/ads/googleads/v15/services/services/custom_audience_service/transports/__init__.py b/google/ads/googleads/v15/services/services/custom_audience_service/transports/__init__.py new file mode 100644 index 000000000..9c2116b0d --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_audience_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomAudienceServiceTransport]] +_transport_registry["grpc"] = CustomAudienceServiceGrpcTransport + +__all__ = ( + "CustomAudienceServiceTransport", + "CustomAudienceServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/custom_audience_service/transports/base.py b/google/ads/googleads/v15/services/services/custom_audience_service/transports/base.py new file mode 100644 index 000000000..2ef539b0f --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_audience_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import custom_audience_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomAudienceServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/custom_audience_service/transports/grpc.py b/google/ads/googleads/v15/services/services/custom_audience_service/transports/grpc.py new file mode 100644 index 000000000..36157d1a0 --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_audience_service/transports/grpc.py @@ -0,0 +1,284 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import custom_audience_service +from .base import CustomAudienceServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomAudienceServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/custom_conversion_goal_service/__init__.py b/google/ads/googleads/v15/services/services/custom_conversion_goal_service/__init__.py new file mode 100644 index 000000000..bba6c1d9c --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_conversion_goal_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomConversionGoalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/custom_conversion_goal_service/client.py b/google/ads/googleads/v15/services/services/custom_conversion_goal_service/client.py new file mode 100644 index 000000000..d9cb3929c --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_conversion_goal_service/client.py @@ -0,0 +1,561 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + custom_conversion_goal_service, +) +from .transports.base import ( + CustomConversionGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomConversionGoalServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomConversionGoalServiceTransport): + # transport is a CustomConversionGoalServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> custom_conversion_goal_service.MutateCustomConversionGoalsResponse: + r"""Creates, updates or removes custom conversion goals. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateCustomConversionGoalsRequest, dict, None]): + The request object. Request message for + [CustomConversionGoalService.MutateCustomConversionGoals][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a custom_conversion_goal_service.MutateCustomConversionGoalsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomConversionGoalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/custom_conversion_goal_service/transports/__init__.py b/google/ads/googleads/v15/services/services/custom_conversion_goal_service/transports/__init__.py new file mode 100644 index 000000000..ee685b6dc --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_conversion_goal_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomConversionGoalServiceTransport]] +_transport_registry["grpc"] = CustomConversionGoalServiceGrpcTransport + +__all__ = ( + "CustomConversionGoalServiceTransport", + "CustomConversionGoalServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/custom_conversion_goal_service/transports/base.py b/google/ads/googleads/v15/services/services/custom_conversion_goal_service/transports/base.py new file mode 100644 index 000000000..7c5a9a99b --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_conversion_goal_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + custom_conversion_goal_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomConversionGoalServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/custom_conversion_goal_service/transports/grpc.py b/google/ads/googleads/v15/services/services/custom_conversion_goal_service/transports/grpc.py new file mode 100644 index 000000000..b646ef2ce --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_conversion_goal_service/transports/grpc.py @@ -0,0 +1,280 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + custom_conversion_goal_service, +) +from .base import CustomConversionGoalServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomConversionGoalServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/custom_interest_service/__init__.py b/google/ads/googleads/v15/services/services/custom_interest_service/__init__.py new file mode 100644 index 000000000..4c9022e63 --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_interest_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomInterestServiceClient",) diff --git a/google/ads/googleads/v15/services/services/custom_interest_service/client.py b/google/ads/googleads/v15/services/services/custom_interest_service/client.py new file mode 100644 index 000000000..b28b87c6f --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_interest_service/client.py @@ -0,0 +1,532 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import custom_interest_service +from .transports.base import CustomInterestServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CustomInterestServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomInterestServiceTransport): + # transport is a CustomInterestServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCustomInterestsRequest, dict, None]): + The request object. Request message for + [CustomInterestService.MutateCustomInterests][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a custom_interest_service.MutateCustomInterestsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomInterestServiceClient",) diff --git a/google/ads/googleads/v15/services/services/custom_interest_service/transports/__init__.py b/google/ads/googleads/v15/services/services/custom_interest_service/transports/__init__.py new file mode 100644 index 000000000..d4192fdfc --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_interest_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomInterestServiceTransport]] +_transport_registry["grpc"] = CustomInterestServiceGrpcTransport + +__all__ = ( + "CustomInterestServiceTransport", + "CustomInterestServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/custom_interest_service/transports/base.py b/google/ads/googleads/v15/services/services/custom_interest_service/transports/base.py new file mode 100644 index 000000000..7fbb6b97c --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_interest_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import custom_interest_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomInterestServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/custom_interest_service/transports/grpc.py b/google/ads/googleads/v15/services/services/custom_interest_service/transports/grpc.py new file mode 100644 index 000000000..503ffde7a --- /dev/null +++ b/google/ads/googleads/v15/services/services/custom_interest_service/transports/grpc.py @@ -0,0 +1,283 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import custom_interest_service +from .base import CustomInterestServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomInterestServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_asset_service/__init__.py b/google/ads/googleads/v15/services/services/customer_asset_service/__init__.py new file mode 100644 index 000000000..895d35627 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_asset_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomerAssetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_asset_service/client.py b/google/ads/googleads/v15/services/services/customer_asset_service/client.py new file mode 100644 index 000000000..411ecd00a --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_asset_service/client.py @@ -0,0 +1,552 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerAssetServiceTransport): + # transport is a CustomerAssetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCustomerAssetsRequest, dict, None]): + The request object. Request message for + [CustomerAssetService.MutateCustomerAssets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_asset_service.MutateCustomerAssetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerAssetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_asset_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_asset_service/transports/__init__.py new file mode 100644 index 000000000..785f25361 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_asset_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerAssetServiceTransport]] +_transport_registry["grpc"] = CustomerAssetServiceGrpcTransport + +__all__ = ( + "CustomerAssetServiceTransport", + "CustomerAssetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_asset_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_asset_service/transports/base.py new file mode 100644 index 000000000..dc49e7ae0 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_asset_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import customer_asset_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomerAssetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_asset_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_asset_service/transports/grpc.py new file mode 100644 index 000000000..64bf41c63 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_asset_service/transports/grpc.py @@ -0,0 +1,281 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import customer_asset_service +from .base import CustomerAssetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomerAssetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_asset_set_service/__init__.py b/google/ads/googleads/v15/services/services/customer_asset_set_service/__init__.py new file mode 100644 index 000000000..0f9b3adab --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_asset_set_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomerAssetSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_asset_set_service/client.py b/google/ads/googleads/v15/services/services/customer_asset_set_service/client.py new file mode 100644 index 000000000..acb2974b3 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_asset_set_service/client.py @@ -0,0 +1,575 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerAssetSetServiceTransport): + # transport is a CustomerAssetSetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> customer_asset_set_service.MutateCustomerAssetSetsResponse: + r"""Creates, or removes customer asset sets. Operation + statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateCustomerAssetSetsRequest, dict, None]): + The request object. Request message for + [CustomerAssetSetService.MutateCustomerAssetSets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_asset_set_service.MutateCustomerAssetSetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerAssetSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_asset_set_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_asset_set_service/transports/__init__.py new file mode 100644 index 000000000..b84eb8a09 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_asset_set_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerAssetSetServiceTransport]] +_transport_registry["grpc"] = CustomerAssetSetServiceGrpcTransport + +__all__ = ( + "CustomerAssetSetServiceTransport", + "CustomerAssetSetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_asset_set_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_asset_set_service/transports/base.py new file mode 100644 index 000000000..6bdd614fe --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_asset_set_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import customer_asset_set_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomerAssetSetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_asset_set_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_asset_set_service/transports/grpc.py new file mode 100644 index 000000000..d1c9e2bd1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_asset_set_service/transports/grpc.py @@ -0,0 +1,276 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import customer_asset_set_service +from .base import CustomerAssetSetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomerAssetSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_client_link_service/__init__.py b/google/ads/googleads/v15/services/services/customer_client_link_service/__init__.py new file mode 100644 index 000000000..489ecab23 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_client_link_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomerClientLinkServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_client_link_service/client.py b/google/ads/googleads/v15/services/services/customer_client_link_service/client.py new file mode 100644 index 000000000..18365a7aa --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_client_link_service/client.py @@ -0,0 +1,552 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import customer_client_link_service +from .transports.base import ( + CustomerClientLinkServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerClientLinkServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerClientLinkServiceTransport): + # transport is a CustomerClientLinkServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCustomerClientLinkRequest, dict, None]): + The request object. Request message for + [CustomerClientLinkService.MutateCustomerClientLink][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operation]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_client_link_service.MutateCustomerClientLinkRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerClientLinkServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_client_link_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_client_link_service/transports/__init__.py new file mode 100644 index 000000000..ed951733f --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_client_link_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerClientLinkServiceTransport]] +_transport_registry["grpc"] = CustomerClientLinkServiceGrpcTransport + +__all__ = ( + "CustomerClientLinkServiceTransport", + "CustomerClientLinkServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_client_link_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_client_link_service/transports/base.py new file mode 100644 index 000000000..741c57cfc --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_client_link_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import customer_client_link_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomerClientLinkServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_client_link_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_client_link_service/transports/grpc.py new file mode 100644 index 000000000..7fc3361b6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_client_link_service/transports/grpc.py @@ -0,0 +1,285 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import customer_client_link_service +from .base import CustomerClientLinkServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomerClientLinkServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_conversion_goal_service/__init__.py b/google/ads/googleads/v15/services/services/customer_conversion_goal_service/__init__.py new file mode 100644 index 000000000..65e6b348d --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_conversion_goal_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomerConversionGoalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_conversion_goal_service/client.py b/google/ads/googleads/v15/services/services/customer_conversion_goal_service/client.py new file mode 100644 index 000000000..c86baae61 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_conversion_goal_service/client.py @@ -0,0 +1,543 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_conversion_goal_service, +) +from .transports.base import ( + CustomerConversionGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerConversionGoalServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerConversionGoalServiceTransport): + # transport is a CustomerConversionGoalServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> customer_conversion_goal_service.MutateCustomerConversionGoalsResponse: + r"""Creates, updates or removes customer conversion + goals. Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateCustomerConversionGoalsRequest, dict, None]): + The request object. Request message for + [CustomerConversionGoalService.MutateCustomerConversionGoals][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_conversion_goal_service.MutateCustomerConversionGoalsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerConversionGoalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_conversion_goal_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_conversion_goal_service/transports/__init__.py new file mode 100644 index 000000000..e5b481411 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_conversion_goal_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerConversionGoalServiceTransport]] +_transport_registry["grpc"] = CustomerConversionGoalServiceGrpcTransport + +__all__ = ( + "CustomerConversionGoalServiceTransport", + "CustomerConversionGoalServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_conversion_goal_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_conversion_goal_service/transports/base.py new file mode 100644 index 000000000..06ef86caf --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_conversion_goal_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_conversion_goal_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomerConversionGoalServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_conversion_goal_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_conversion_goal_service/transports/grpc.py new file mode 100644 index 000000000..f6f30f1b1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_conversion_goal_service/transports/grpc.py @@ -0,0 +1,281 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_conversion_goal_service, +) +from .base import CustomerConversionGoalServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomerConversionGoalServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_customizer_service/__init__.py b/google/ads/googleads/v15/services/services/customer_customizer_service/__init__.py new file mode 100644 index 000000000..3fec78bc7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_customizer_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomerCustomizerServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_customizer_service/client.py b/google/ads/googleads/v15/services/services/customer_customizer_service/client.py new file mode 100644 index 000000000..18b3a4245 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_customizer_service/client.py @@ -0,0 +1,562 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerCustomizerServiceTransport): + # transport is a CustomerCustomizerServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> customer_customizer_service.MutateCustomerCustomizersResponse: + r"""Creates, updates or removes customer customizers. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateCustomerCustomizersRequest, dict, None]): + The request object. Request message for + [CustomerCustomizerService.MutateCustomerCustomizers][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_customizer_service.MutateCustomerCustomizersRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerCustomizerServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_customizer_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_customizer_service/transports/__init__.py new file mode 100644 index 000000000..8f3b884cb --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_customizer_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerCustomizerServiceTransport]] +_transport_registry["grpc"] = CustomerCustomizerServiceGrpcTransport + +__all__ = ( + "CustomerCustomizerServiceTransport", + "CustomerCustomizerServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_customizer_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_customizer_service/transports/base.py new file mode 100644 index 000000000..fc95a60a8 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_customizer_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import customer_customizer_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomerCustomizerServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_customizer_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_customizer_service/transports/grpc.py new file mode 100644 index 000000000..6faf9c944 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_customizer_service/transports/grpc.py @@ -0,0 +1,278 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import customer_customizer_service +from .base import CustomerCustomizerServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomerCustomizerServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_extension_setting_service/__init__.py b/google/ads/googleads/v15/services/services/customer_extension_setting_service/__init__.py new file mode 100644 index 000000000..48102065b --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_extension_setting_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 CustomerExtensionSettingServiceClient + +__all__ = ("CustomerExtensionSettingServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_extension_setting_service/client.py b/google/ads/googleads/v15/services/services/customer_extension_setting_service/client.py new file mode 100644 index 000000000..34fee65fd --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_extension_setting_service/client.py @@ -0,0 +1,576 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_extension_setting_service, +) +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + CustomerExtensionSettingServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerExtensionSettingServiceGrpcTransport + + +class CustomerExtensionSettingServiceClientMeta(type): + """Metaclass for the CustomerExtensionSettingService 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[CustomerExtensionSettingServiceTransport]] + _transport_registry["grpc"] = CustomerExtensionSettingServiceGrpcTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerExtensionSettingServiceTransport]: + """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 CustomerExtensionSettingServiceClient( + metaclass=CustomerExtensionSettingServiceClientMeta +): + """Service to manage customer extension 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + CustomerExtensionSettingServiceClient: 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: + CustomerExtensionSettingServiceClient: 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) -> CustomerExtensionSettingServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerExtensionSettingServiceTransport: The transport used by the client + instance. + """ + return self._transport + + def __enter__(self) -> "CustomerExtensionSettingServiceClient": + 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() + + @staticmethod + def customer_extension_setting_path( + customer_id: str, + extension_type: str, + ) -> str: + """Returns a fully-qualified customer_extension_setting string.""" + return "customers/{customer_id}/customerExtensionSettings/{extension_type}".format( + customer_id=customer_id, + extension_type=extension_type, + ) + + @staticmethod + def parse_customer_extension_setting_path(path: str) -> Dict[str, str]: + """Parses a customer_extension_setting path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerExtensionSettings/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def extension_feed_item_path( + customer_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified extension_feed_item string.""" + return ( + "customers/{customer_id}/extensionFeedItems/{feed_item_id}".format( + customer_id=customer_id, + feed_item_id=feed_item_id, + ) + ) + + @staticmethod + def parse_extension_feed_item_path(path: str) -> Dict[str, str]: + """Parses a extension_feed_item path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/extensionFeedItems/(?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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, CustomerExtensionSettingServiceTransport] + ] = 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 extension 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, CustomerExtensionSettingServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerExtensionSettingServiceTransport): + # transport is a CustomerExtensionSettingServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def mutate_customer_extension_settings( + self, + request: Optional[ + Union[ + customer_extension_setting_service.MutateCustomerExtensionSettingsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + customer_extension_setting_service.CustomerExtensionSettingOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> customer_extension_setting_service.MutateCustomerExtensionSettingsResponse: + r"""Creates, updates, or removes customer extension settings. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `CriterionError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `ExtensionSettingError <>`__ + `FieldError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateCustomerExtensionSettingsRequest, dict, None]): + The request object. Request message for + [CustomerExtensionSettingService.MutateCustomerExtensionSettings][google.ads.googleads.v15.services.CustomerExtensionSettingService.MutateCustomerExtensionSettings]. + customer_id (str): + Required. The ID of the customer + whose customer extension 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.v15.services.types.CustomerExtensionSettingOperation]): + Required. The list of operations to + perform on individual customer extension + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateCustomerExtensionSettingsResponse: + Response message for a customer + extension setting 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_extension_setting_service.MutateCustomerExtensionSettingsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, + customer_extension_setting_service.MutateCustomerExtensionSettingsRequest, + ): + request = customer_extension_setting_service.MutateCustomerExtensionSettingsRequest( + request + ) + # 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_extension_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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerExtensionSettingServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_extension_setting_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_extension_setting_service/transports/__init__.py new file mode 100644 index 000000000..1ec9134bc --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_extension_setting_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 CustomerExtensionSettingServiceTransport +from .grpc import CustomerExtensionSettingServiceGrpcTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerExtensionSettingServiceTransport]] +_transport_registry["grpc"] = CustomerExtensionSettingServiceGrpcTransport + +__all__ = ( + "CustomerExtensionSettingServiceTransport", + "CustomerExtensionSettingServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_extension_setting_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_extension_setting_service/transports/base.py new file mode 100644 index 000000000..a880b499e --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_extension_setting_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_extension_setting_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class CustomerExtensionSettingServiceTransport(abc.ABC): + """Abstract transport class for CustomerExtensionSettingService.""" + + 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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer_extension_settings: gapic_v1.method.wrap_method( + self.mutate_customer_extension_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 mutate_customer_extension_settings( + self, + ) -> Callable[ + [ + customer_extension_setting_service.MutateCustomerExtensionSettingsRequest + ], + Union[ + customer_extension_setting_service.MutateCustomerExtensionSettingsResponse, + Awaitable[ + customer_extension_setting_service.MutateCustomerExtensionSettingsResponse + ], + ], + ]: + raise NotImplementedError() + + +__all__ = ("CustomerExtensionSettingServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_extension_setting_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_extension_setting_service/transports/grpc.py new file mode 100644 index 000000000..072232e97 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_extension_setting_service/transports/grpc.py @@ -0,0 +1,295 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_extension_setting_service, +) +from .base import CustomerExtensionSettingServiceTransport, DEFAULT_CLIENT_INFO + + +class CustomerExtensionSettingServiceGrpcTransport( + CustomerExtensionSettingServiceTransport +): + """gRPC backend transport for CustomerExtensionSettingService. + + Service to manage customer extension 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def mutate_customer_extension_settings( + self, + ) -> Callable[ + [ + customer_extension_setting_service.MutateCustomerExtensionSettingsRequest + ], + customer_extension_setting_service.MutateCustomerExtensionSettingsResponse, + ]: + r"""Return a callable for the mutate customer extension + settings method over gRPC. + + Creates, updates, or removes customer extension settings. + Operation statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `CriterionError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `ExtensionSettingError <>`__ + `FieldError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateCustomerExtensionSettingsRequest], + ~.MutateCustomerExtensionSettingsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_extension_settings" not in self._stubs: + self._stubs[ + "mutate_customer_extension_settings" + ] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.CustomerExtensionSettingService/MutateCustomerExtensionSettings", + request_serializer=customer_extension_setting_service.MutateCustomerExtensionSettingsRequest.serialize, + response_deserializer=customer_extension_setting_service.MutateCustomerExtensionSettingsResponse.deserialize, + ) + return self._stubs["mutate_customer_extension_settings"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("CustomerExtensionSettingServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_feed_service/__init__.py b/google/ads/googleads/v15/services/services/customer_feed_service/__init__.py new file mode 100644 index 000000000..9b8cc8e52 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_feed_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 CustomerFeedServiceClient + +__all__ = ("CustomerFeedServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_feed_service/client.py b/google/ads/googleads/v15/services/services/customer_feed_service/client.py new file mode 100644 index 000000000..d9c74d08c --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_feed_service/client.py @@ -0,0 +1,553 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import customer_feed_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import CustomerFeedServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CustomerFeedServiceGrpcTransport + + +class CustomerFeedServiceClientMeta(type): + """Metaclass for the CustomerFeedService 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[CustomerFeedServiceTransport]] + _transport_registry["grpc"] = CustomerFeedServiceGrpcTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[CustomerFeedServiceTransport]: + """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 CustomerFeedServiceClient(metaclass=CustomerFeedServiceClientMeta): + """Service to manage customer feeds.""" + + @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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + CustomerFeedServiceClient: 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: + CustomerFeedServiceClient: 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) -> CustomerFeedServiceTransport: + """Returns the transport used by the client instance. + + Returns: + CustomerFeedServiceTransport: The transport used by the client + instance. + """ + return self._transport + + def __enter__(self) -> "CustomerFeedServiceClient": + 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() + + @staticmethod + def customer_feed_path( + customer_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified customer_feed string.""" + return "customers/{customer_id}/customerFeeds/{feed_id}".format( + customer_id=customer_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_customer_feed_path(path: str) -> Dict[str, str]: + """Parses a customer_feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerFeeds/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_path( + customer_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified feed string.""" + return "customers/{customer_id}/feeds/{feed_id}".format( + customer_id=customer_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_feed_path(path: str) -> Dict[str, str]: + """Parses a feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feeds/(?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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, CustomerFeedServiceTransport]] = 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 feed 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, CustomerFeedServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerFeedServiceTransport): + # transport is a CustomerFeedServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def mutate_customer_feeds( + self, + request: Optional[ + Union[customer_feed_service.MutateCustomerFeedsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[customer_feed_service.CustomerFeedOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> customer_feed_service.MutateCustomerFeedsResponse: + r"""Creates, updates, or removes customer feeds. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `CustomerFeedError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `FunctionError <>`__ `FunctionParsingError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NotEmptyError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateCustomerFeedsRequest, dict, None]): + The request object. Request message for + [CustomerFeedService.MutateCustomerFeeds][google.ads.googleads.v15.services.CustomerFeedService.MutateCustomerFeeds]. + customer_id (str): + Required. The ID of the customer + whose customer feeds 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.v15.services.types.CustomerFeedOperation]): + Required. The list of operations to + perform on individual customer feeds. + + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateCustomerFeedsResponse: + Response message for a customer feed + 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_feed_service.MutateCustomerFeedsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, customer_feed_service.MutateCustomerFeedsRequest + ): + request = customer_feed_service.MutateCustomerFeedsRequest(request) + # 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_feeds + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerFeedServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_feed_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_feed_service/transports/__init__.py new file mode 100644 index 000000000..39eba99bb --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_feed_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 CustomerFeedServiceTransport +from .grpc import CustomerFeedServiceGrpcTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerFeedServiceTransport]] +_transport_registry["grpc"] = CustomerFeedServiceGrpcTransport + +__all__ = ( + "CustomerFeedServiceTransport", + "CustomerFeedServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_feed_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_feed_service/transports/base.py new file mode 100644 index 000000000..e4acb0021 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_feed_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import customer_feed_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class CustomerFeedServiceTransport(abc.ABC): + """Abstract transport class for CustomerFeedService.""" + + 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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_customer_feeds: gapic_v1.method.wrap_method( + self.mutate_customer_feeds, + 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_feeds( + self, + ) -> Callable[ + [customer_feed_service.MutateCustomerFeedsRequest], + Union[ + customer_feed_service.MutateCustomerFeedsResponse, + Awaitable[customer_feed_service.MutateCustomerFeedsResponse], + ], + ]: + raise NotImplementedError() + + +__all__ = ("CustomerFeedServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_feed_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_feed_service/transports/grpc.py new file mode 100644 index 000000000..bf3c7f2c4 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_feed_service/transports/grpc.py @@ -0,0 +1,287 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import customer_feed_service +from .base import CustomerFeedServiceTransport, DEFAULT_CLIENT_INFO + + +class CustomerFeedServiceGrpcTransport(CustomerFeedServiceTransport): + """gRPC backend transport for CustomerFeedService. + + Service to manage customer feeds. + + This 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def mutate_customer_feeds( + self, + ) -> Callable[ + [customer_feed_service.MutateCustomerFeedsRequest], + customer_feed_service.MutateCustomerFeedsResponse, + ]: + r"""Return a callable for the mutate customer feeds method over gRPC. + + Creates, updates, or removes customer feeds. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `CustomerFeedError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FieldError <>`__ `FieldMaskError <>`__ + `FunctionError <>`__ `FunctionParsingError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NotEmptyError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Returns: + Callable[[~.MutateCustomerFeedsRequest], + ~.MutateCustomerFeedsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_feeds" not in self._stubs: + self._stubs[ + "mutate_customer_feeds" + ] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.CustomerFeedService/MutateCustomerFeeds", + request_serializer=customer_feed_service.MutateCustomerFeedsRequest.serialize, + response_deserializer=customer_feed_service.MutateCustomerFeedsResponse.deserialize, + ) + return self._stubs["mutate_customer_feeds"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("CustomerFeedServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_label_service/__init__.py b/google/ads/googleads/v15/services/services/customer_label_service/__init__.py new file mode 100644 index 000000000..0caf79e49 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_label_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomerLabelServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_label_service/client.py b/google/ads/googleads/v15/services/services/customer_label_service/client.py new file mode 100644 index 000000000..d6a345c06 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_label_service/client.py @@ -0,0 +1,565 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerLabelServiceTransport): + # transport is a CustomerLabelServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCustomerLabelsRequest, dict, None]): + The request object. Request message for + [CustomerLabelService.MutateCustomerLabels][google.ads.googleads.v15.services.CustomerLabelService.MutateCustomerLabels]. + 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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_label_service.MutateCustomerLabelsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerLabelServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_label_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_label_service/transports/__init__.py new file mode 100644 index 000000000..665ef3ae7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_label_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerLabelServiceTransport]] +_transport_registry["grpc"] = CustomerLabelServiceGrpcTransport + +__all__ = ( + "CustomerLabelServiceTransport", + "CustomerLabelServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_label_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_label_service/transports/base.py new file mode 100644 index 000000000..9d4fb08d9 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_label_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import customer_label_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomerLabelServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_label_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_label_service/transports/grpc.py new file mode 100644 index 000000000..fc9d22f2f --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_label_service/transports/grpc.py @@ -0,0 +1,281 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import customer_label_service +from .base import CustomerLabelServiceTransport, DEFAULT_CLIENT_INFO + + +class CustomerLabelServiceGrpcTransport(CustomerLabelServiceTransport): + """gRPC backend transport for CustomerLabelService. + + Service to manage labels on 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomerLabelServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/__init__.py b/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/__init__.py new file mode 100644 index 000000000..b0a7aa704 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomerLifecycleGoalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/client.py b/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/client.py new file mode 100644 index 000000000..c3a22d17a --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/client.py @@ -0,0 +1,549 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_lifecycle_goal_service, +) +from .transports.base import ( + CustomerLifecycleGoalServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerLifecycleGoalServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerLifecycleGoalServiceTransport): + # transport is a CustomerLifecycleGoalServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.ConfigureCustomerLifecycleGoalsRequest, dict, None]): + The request object. Request message for + [CustomerLifecycleService.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.ConfigureCustomerLifecycleGoalsResponse: + Response message for + [CustomerLifecycleService.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. + has_flattened_params = any([customer_id, operation]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_lifecycle_goal_service.ConfigureCustomerLifecycleGoalsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerLifecycleGoalServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/transports/__init__.py new file mode 100644 index 000000000..59abcdf6a --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerLifecycleGoalServiceTransport]] +_transport_registry["grpc"] = CustomerLifecycleGoalServiceGrpcTransport + +__all__ = ( + "CustomerLifecycleGoalServiceTransport", + "CustomerLifecycleGoalServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/transports/base.py new file mode 100644 index 000000000..41e3efea6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_lifecycle_goal_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomerLifecycleGoalServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/transports/grpc.py new file mode 100644 index 000000000..854841af0 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_lifecycle_goal_service/transports/grpc.py @@ -0,0 +1,287 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_lifecycle_goal_service, +) +from .base import CustomerLifecycleGoalServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomerLifecycleGoalServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_manager_link_service/__init__.py b/google/ads/googleads/v15/services/services/customer_manager_link_service/__init__.py new file mode 100644 index 000000000..8fb94b82a --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_manager_link_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomerManagerLinkServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_manager_link_service/client.py b/google/ads/googleads/v15/services/services/customer_manager_link_service/client.py new file mode 100644 index 000000000..a913dbb8b --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_manager_link_service/client.py @@ -0,0 +1,687 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_manager_link_service, +) +from .transports.base import ( + CustomerManagerLinkServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerManagerLinkServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerManagerLinkServiceTransport): + # transport is a CustomerManagerLinkServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCustomerManagerLinkRequest, dict, None]): + The request object. Request message for + [CustomerManagerLinkService.MutateCustomerManagerLink][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_manager_link_service.MutateCustomerManagerLinkRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.MoveManagerLinkRequest, dict, None]): + The request object. Request message for + [CustomerManagerLinkService.MoveManagerLink][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any( + [customer_id, previous_customer_manager_link, new_manager] + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_manager_link_service.MoveManagerLinkRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerManagerLinkServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_manager_link_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_manager_link_service/transports/__init__.py new file mode 100644 index 000000000..fad944607 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_manager_link_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerManagerLinkServiceTransport]] +_transport_registry["grpc"] = CustomerManagerLinkServiceGrpcTransport + +__all__ = ( + "CustomerManagerLinkServiceTransport", + "CustomerManagerLinkServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_manager_link_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_manager_link_service/transports/base.py new file mode 100644 index 000000000..e357cfef6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_manager_link_service/transports/base.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_manager_link_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomerManagerLinkServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_manager_link_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_manager_link_service/transports/grpc.py new file mode 100644 index 000000000..689398b8e --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_manager_link_service/transports/grpc.py @@ -0,0 +1,324 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_manager_link_service, +) +from .base import CustomerManagerLinkServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomerManagerLinkServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_negative_criterion_service/__init__.py b/google/ads/googleads/v15/services/services/customer_negative_criterion_service/__init__.py new file mode 100644 index 000000000..9f20734d7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_negative_criterion_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomerNegativeCriterionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_negative_criterion_service/client.py b/google/ads/googleads/v15/services/services/customer_negative_criterion_service/client.py new file mode 100644 index 000000000..f7982abb9 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_negative_criterion_service/client.py @@ -0,0 +1,563 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerNegativeCriterionServiceTransport): + # transport is a CustomerNegativeCriterionServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCustomerNegativeCriteriaRequest, dict, None]): + The request object. Request message for + [CustomerNegativeCriterionService.MutateCustomerNegativeCriteria][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_negative_criterion_service.MutateCustomerNegativeCriteriaRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerNegativeCriterionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_negative_criterion_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_negative_criterion_service/transports/__init__.py new file mode 100644 index 000000000..64991f5c5 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_negative_criterion_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerNegativeCriterionServiceTransport]] +_transport_registry["grpc"] = CustomerNegativeCriterionServiceGrpcTransport + +__all__ = ( + "CustomerNegativeCriterionServiceTransport", + "CustomerNegativeCriterionServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_negative_criterion_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_negative_criterion_service/transports/base.py new file mode 100644 index 000000000..a01064aca --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_negative_criterion_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_negative_criterion_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomerNegativeCriterionServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_negative_criterion_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_negative_criterion_service/transports/grpc.py new file mode 100644 index 000000000..6e9df30ff --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_negative_criterion_service/transports/grpc.py @@ -0,0 +1,288 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_negative_criterion_service, +) +from .base import CustomerNegativeCriterionServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomerNegativeCriterionServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_service/__init__.py b/google/ads/googleads/v15/services/services/customer_service/__init__.py new file mode 100644 index 000000000..6c6b16b89 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomerServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_service/client.py b/google/ads/googleads/v15/services/services/customer_service/client.py new file mode 100644 index 000000000..89c6c03fd --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_service/client.py @@ -0,0 +1,687 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.resources.types import customer +from google.ads.googleads.v15.services.types import customer_service +from .transports.base import CustomerServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import CustomerServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerServiceTransport): + # transport is a CustomerServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCustomerRequest, dict, None]): + The request object. Request message for + [CustomerService.MutateCustomer][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operation]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_service.MutateCustomerRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.ListAccessibleCustomersRequest, dict, None]): + The request object. Request message for + [CustomerService.ListAccessibleCustomers][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.ListAccessibleCustomersResponse: + Response message for + [CustomerService.ListAccessibleCustomers][google.ads.googleads.v15.services.CustomerService.ListAccessibleCustomers]. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a customer_service.ListAccessibleCustomersRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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 + ] + + # 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, str]] = (), + ) -> 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.v15.services.types.CreateCustomerClientRequest, dict, None]): + The request object. Request message for + [CustomerService.CreateCustomerClient][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, customer_client]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_service.CreateCustomerClientRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_service/transports/__init__.py new file mode 100644 index 000000000..fcd0038e3 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerServiceTransport]] +_transport_registry["grpc"] = CustomerServiceGrpcTransport + +__all__ = ( + "CustomerServiceTransport", + "CustomerServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_service/transports/base.py new file mode 100644 index 000000000..ae53a01d1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_service/transports/base.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import customer_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomerServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_service/transports/grpc.py new file mode 100644 index 000000000..26bcdf123 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_service/transports/grpc.py @@ -0,0 +1,352 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import customer_service +from .base import CustomerServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomerServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/__init__.py b/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/__init__.py new file mode 100644 index 000000000..e7bc4c6a0 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomerSkAdNetworkConversionValueSchemaServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/client.py b/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/client.py new file mode 100644 index 000000000..3616b5fa5 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/client.py @@ -0,0 +1,510 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_sk_ad_network_conversion_value_schema_service, +) +from .transports.base import ( + CustomerSkAdNetworkConversionValueSchemaServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ( + CustomerSkAdNetworkConversionValueSchemaServiceGrpcTransport, +) + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance( + transport, CustomerSkAdNetworkConversionValueSchemaServiceTransport + ): + # transport is a CustomerSkAdNetworkConversionValueSchemaServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCustomerSkAdNetworkConversionValueSchemaRequest, dict, None]): + The request object. Request message for + [CustomerSkAdNetworkConversionValueSchemaService.MutateCustomerSkAdNetworkConversionValueSchema][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateCustomerSkAdNetworkConversionValueSchemaResponse: + Response message for + MutateCustomerSkAdNetworkConversionValueSchema. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a customer_sk_ad_network_conversion_value_schema_service.MutateCustomerSkAdNetworkConversionValueSchemaRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerSkAdNetworkConversionValueSchemaServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/__init__.py new file mode 100644 index 000000000..cd0b73a00 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/__init__.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerSkAdNetworkConversionValueSchemaServiceTransport]] +_transport_registry[ + "grpc" +] = CustomerSkAdNetworkConversionValueSchemaServiceGrpcTransport + +__all__ = ( + "CustomerSkAdNetworkConversionValueSchemaServiceTransport", + "CustomerSkAdNetworkConversionValueSchemaServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/base.py new file mode 100644 index 000000000..7b58c4208 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_sk_ad_network_conversion_value_schema_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomerSkAdNetworkConversionValueSchemaServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/grpc.py new file mode 100644 index 000000000..b929a2f16 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_sk_ad_network_conversion_value_schema_service/transports/grpc.py @@ -0,0 +1,294 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_sk_ad_network_conversion_value_schema_service, +) +from .base import ( + CustomerSkAdNetworkConversionValueSchemaServiceTransport, + DEFAULT_CLIENT_INFO, +) + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomerSkAdNetworkConversionValueSchemaServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/__init__.py b/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/__init__.py new file mode 100644 index 000000000..4bb20f792 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomerUserAccessInvitationServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/client.py b/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/client.py new file mode 100644 index 000000000..1aff452cd --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/client.py @@ -0,0 +1,537 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_user_access_invitation_service, +) +from .transports.base import ( + CustomerUserAccessInvitationServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerUserAccessInvitationServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerUserAccessInvitationServiceTransport): + # transport is a CustomerUserAccessInvitationServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCustomerUserAccessInvitationRequest, dict, None]): + The request object. Request message for + [CustomerUserAccessInvitationService.MutateCustomerUserAccessInvitation][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operation]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_user_access_invitation_service.MutateCustomerUserAccessInvitationRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerUserAccessInvitationServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/transports/__init__.py new file mode 100644 index 000000000..faa4629ec --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerUserAccessInvitationServiceTransport]] +_transport_registry["grpc"] = CustomerUserAccessInvitationServiceGrpcTransport + +__all__ = ( + "CustomerUserAccessInvitationServiceTransport", + "CustomerUserAccessInvitationServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/transports/base.py new file mode 100644 index 000000000..9c5cbff34 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_user_access_invitation_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomerUserAccessInvitationServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/transports/grpc.py new file mode 100644 index 000000000..000b2077d --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_user_access_invitation_service/transports/grpc.py @@ -0,0 +1,291 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + customer_user_access_invitation_service, +) +from .base import ( + CustomerUserAccessInvitationServiceTransport, + DEFAULT_CLIENT_INFO, +) + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomerUserAccessInvitationServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_user_access_service/__init__.py b/google/ads/googleads/v15/services/services/customer_user_access_service/__init__.py new file mode 100644 index 000000000..2a1ddde23 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_user_access_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomerUserAccessServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_user_access_service/client.py b/google/ads/googleads/v15/services/services/customer_user_access_service/client.py new file mode 100644 index 000000000..3bf3ce944 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_user_access_service/client.py @@ -0,0 +1,535 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import customer_user_access_service +from .transports.base import ( + CustomerUserAccessServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import CustomerUserAccessServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomerUserAccessServiceTransport): + # transport is a CustomerUserAccessServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateCustomerUserAccessRequest, dict, None]): + The request object. Mutate Request for + [CustomerUserAccessService.MutateCustomerUserAccess][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operation]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customer_user_access_service.MutateCustomerUserAccessRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomerUserAccessServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customer_user_access_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customer_user_access_service/transports/__init__.py new file mode 100644 index 000000000..8448a0854 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_user_access_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomerUserAccessServiceTransport]] +_transport_registry["grpc"] = CustomerUserAccessServiceGrpcTransport + +__all__ = ( + "CustomerUserAccessServiceTransport", + "CustomerUserAccessServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customer_user_access_service/transports/base.py b/google/ads/googleads/v15/services/services/customer_user_access_service/transports/base.py new file mode 100644 index 000000000..0bf59af76 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_user_access_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import customer_user_access_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomerUserAccessServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customer_user_access_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customer_user_access_service/transports/grpc.py new file mode 100644 index 000000000..ef360d78e --- /dev/null +++ b/google/ads/googleads/v15/services/services/customer_user_access_service/transports/grpc.py @@ -0,0 +1,284 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import customer_user_access_service +from .base import CustomerUserAccessServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomerUserAccessServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/customizer_attribute_service/__init__.py b/google/ads/googleads/v15/services/services/customizer_attribute_service/__init__.py new file mode 100644 index 000000000..cddcaae83 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customizer_attribute_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("CustomizerAttributeServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customizer_attribute_service/client.py b/google/ads/googleads/v15/services/services/customizer_attribute_service/client.py new file mode 100644 index 000000000..b13d2cafc --- /dev/null +++ b/google/ads/googleads/v15/services/services/customizer_attribute_service/client.py @@ -0,0 +1,542 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, CustomizerAttributeServiceTransport): + # transport is a CustomizerAttributeServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> customizer_attribute_service.MutateCustomizerAttributesResponse: + r"""Creates, updates or removes customizer attributes. + Operation statuses are returned. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateCustomizerAttributesRequest, dict, None]): + The request object. Request message for + [CustomizerAttributeService.MutateCustomizerAttributes][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a customizer_attribute_service.MutateCustomizerAttributesRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("CustomizerAttributeServiceClient",) diff --git a/google/ads/googleads/v15/services/services/customizer_attribute_service/transports/__init__.py b/google/ads/googleads/v15/services/services/customizer_attribute_service/transports/__init__.py new file mode 100644 index 000000000..d43203d0b --- /dev/null +++ b/google/ads/googleads/v15/services/services/customizer_attribute_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[CustomizerAttributeServiceTransport]] +_transport_registry["grpc"] = CustomizerAttributeServiceGrpcTransport + +__all__ = ( + "CustomizerAttributeServiceTransport", + "CustomizerAttributeServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/customizer_attribute_service/transports/base.py b/google/ads/googleads/v15/services/services/customizer_attribute_service/transports/base.py new file mode 100644 index 000000000..bc082ac44 --- /dev/null +++ b/google/ads/googleads/v15/services/services/customizer_attribute_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import customizer_attribute_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("CustomizerAttributeServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/customizer_attribute_service/transports/grpc.py b/google/ads/googleads/v15/services/services/customizer_attribute_service/transports/grpc.py new file mode 100644 index 000000000..2dd5b92ee --- /dev/null +++ b/google/ads/googleads/v15/services/services/customizer_attribute_service/transports/grpc.py @@ -0,0 +1,278 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import customizer_attribute_service +from .base import CustomizerAttributeServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("CustomizerAttributeServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/experiment_arm_service/__init__.py b/google/ads/googleads/v15/services/services/experiment_arm_service/__init__.py new file mode 100644 index 000000000..63c55177c --- /dev/null +++ b/google/ads/googleads/v15/services/services/experiment_arm_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("ExperimentArmServiceClient",) diff --git a/google/ads/googleads/v15/services/services/experiment_arm_service/client.py b/google/ads/googleads/v15/services/services/experiment_arm_service/client.py new file mode 100644 index 000000000..2ff7a1b77 --- /dev/null +++ b/google/ads/googleads/v15/services/services/experiment_arm_service/client.py @@ -0,0 +1,572 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ExperimentArmServiceTransport): + # transport is a ExperimentArmServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateExperimentArmsRequest, dict, None]): + The request object. Request message for + [ExperimentArmService.MutateExperimentArms][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a experiment_arm_service.MutateExperimentArmsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ExperimentArmServiceClient",) diff --git a/google/ads/googleads/v15/services/services/experiment_arm_service/transports/__init__.py b/google/ads/googleads/v15/services/services/experiment_arm_service/transports/__init__.py new file mode 100644 index 000000000..b3a6b84f6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/experiment_arm_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ExperimentArmServiceTransport]] +_transport_registry["grpc"] = ExperimentArmServiceGrpcTransport + +__all__ = ( + "ExperimentArmServiceTransport", + "ExperimentArmServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/experiment_arm_service/transports/base.py b/google/ads/googleads/v15/services/services/experiment_arm_service/transports/base.py new file mode 100644 index 000000000..e98615b78 --- /dev/null +++ b/google/ads/googleads/v15/services/services/experiment_arm_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import experiment_arm_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("ExperimentArmServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/experiment_arm_service/transports/grpc.py b/google/ads/googleads/v15/services/services/experiment_arm_service/transports/grpc.py new file mode 100644 index 000000000..4ff3b8ec2 --- /dev/null +++ b/google/ads/googleads/v15/services/services/experiment_arm_service/transports/grpc.py @@ -0,0 +1,281 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import experiment_arm_service +from .base import ExperimentArmServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("ExperimentArmServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/experiment_service/__init__.py b/google/ads/googleads/v15/services/services/experiment_service/__init__.py new file mode 100644 index 000000000..41fa5c179 --- /dev/null +++ b/google/ads/googleads/v15/services/services/experiment_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("ExperimentServiceClient",) diff --git a/google/ads/googleads/v15/services/services/experiment_service/client.py b/google/ads/googleads/v15/services/services/experiment_service/client.py new file mode 100644 index 000000000..70d67f611 --- /dev/null +++ b/google/ads/googleads/v15/services/services/experiment_service/client.py @@ -0,0 +1,1075 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.services.experiment_service import pagers +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ExperimentServiceTransport): + # transport is a ExperimentServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateExperimentsRequest, dict, None]): + The request object. Request message for + [ExperimentService.MutateExperiments][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a experiment_service.MutateExperimentsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.EndExperimentRequest, dict, None]): + The request object. Request message for + [ExperimentService.EndExperiment][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + """ + # Create or coerce a protobuf request object. + # Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([experiment]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a experiment_service.EndExperimentRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.ListExperimentAsyncErrorsRequest, dict, None]): + The request object. Request message for + [ExperimentService.ListExperimentAsyncErrors][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.services.experiment_service.pagers.ListExperimentAsyncErrorsPager: + Response message for + [ExperimentService.ListExperimentAsyncErrors][google.ads.googleads.v15.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. + has_flattened_params = any([resource_name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a experiment_service.ListExperimentAsyncErrorsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, + 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, str]] = (), + ) -> 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.v15.services.types.GraduateExperimentRequest, dict, None]): + The request object. Request message for + [ExperimentService.GraduateExperiment][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + """ + # Create or coerce a protobuf request object. + # Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([experiment, campaign_budget_mappings]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a experiment_service.GraduateExperimentRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.ScheduleExperimentRequest, dict, None]): + The request object. Request message for + [ExperimentService.ScheduleExperiment][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.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. + has_flattened_params = any([resource_name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a experiment_service.ScheduleExperimentRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.PromoteExperimentRequest, dict, None]): + The request object. Request message for + [ExperimentService.PromoteExperiment][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.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. + has_flattened_params = any([resource_name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a experiment_service.PromoteExperimentRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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 + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ExperimentServiceClient",) diff --git a/google/ads/googleads/v15/services/services/experiment_service/pagers.py b/google/ads/googleads/v15/services/services/experiment_service/pagers.py new file mode 100644 index 000000000..60ac143d7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/experiment_service/pagers.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Any, Callable, Iterable, Iterator, Sequence, Tuple + +from google.ads.googleads.v15.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.v15.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.v15.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, + metadata: Sequence[Tuple[str, str]] = (), + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (:class:`google.ads.googleads.v15.services.types.ListExperimentAsyncErrorsRequest`): + The initial request object. + response (:class:`google.ads.googleads.v15.services.types.ListExperimentAsyncErrorsResponse`): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = experiment_service.ListExperimentAsyncErrorsRequest( + request + ) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages( + self, + ) -> Iterable[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, 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) diff --git a/google/ads/googleads/v15/services/services/experiment_service/transports/__init__.py b/google/ads/googleads/v15/services/services/experiment_service/transports/__init__.py new file mode 100644 index 000000000..f8658ea9c --- /dev/null +++ b/google/ads/googleads/v15/services/services/experiment_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ExperimentServiceTransport]] +_transport_registry["grpc"] = ExperimentServiceGrpcTransport + +__all__ = ( + "ExperimentServiceTransport", + "ExperimentServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/experiment_service/transports/base.py b/google/ads/googleads/v15/services/services/experiment_service/transports/base.py new file mode 100644 index 000000000..b3188b3aa --- /dev/null +++ b/google/ads/googleads/v15/services/services/experiment_service/transports/base.py @@ -0,0 +1,236 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import experiment_service +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import empty_pb2 # type: ignore + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("ExperimentServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/experiment_service/transports/grpc.py b/google/ads/googleads/v15/services/services/experiment_service/transports/grpc.py new file mode 100644 index 000000000..f3024040a --- /dev/null +++ b/google/ads/googleads/v15/services/services/experiment_service/transports/grpc.py @@ -0,0 +1,485 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.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 + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client: Optional[operations_v1.OperationsClient] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def operations_client(self) -> operations_v1.OperationsClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsClient( + self.grpc_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.ExperimentService/PromoteExperiment", + request_serializer=experiment_service.PromoteExperimentRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["promote_experiment"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("ExperimentServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/extension_feed_item_service/__init__.py b/google/ads/googleads/v15/services/services/extension_feed_item_service/__init__.py new file mode 100644 index 000000000..932c6112a --- /dev/null +++ b/google/ads/googleads/v15/services/services/extension_feed_item_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 ExtensionFeedItemServiceClient + +__all__ = ("ExtensionFeedItemServiceClient",) diff --git a/google/ads/googleads/v15/services/services/extension_feed_item_service/client.py b/google/ads/googleads/v15/services/services/extension_feed_item_service/client.py new file mode 100644 index 000000000..db41dfcda --- /dev/null +++ b/google/ads/googleads/v15/services/services/extension_feed_item_service/client.py @@ -0,0 +1,628 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import extension_feed_item_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + ExtensionFeedItemServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ExtensionFeedItemServiceGrpcTransport + + +class ExtensionFeedItemServiceClientMeta(type): + """Metaclass for the ExtensionFeedItemService 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[ExtensionFeedItemServiceTransport]] + _transport_registry["grpc"] = ExtensionFeedItemServiceGrpcTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ExtensionFeedItemServiceTransport]: + """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 ExtensionFeedItemServiceClient( + metaclass=ExtensionFeedItemServiceClientMeta +): + """Service to manage extension feed items.""" + + @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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + ExtensionFeedItemServiceClient: 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: + ExtensionFeedItemServiceClient: 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) -> ExtensionFeedItemServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ExtensionFeedItemServiceTransport: The transport used by the client + instance. + """ + return self._transport + + def __enter__(self) -> "ExtensionFeedItemServiceClient": + 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() + + @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 extension_feed_item_path( + customer_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified extension_feed_item string.""" + return ( + "customers/{customer_id}/extensionFeedItems/{feed_item_id}".format( + customer_id=customer_id, + feed_item_id=feed_item_id, + ) + ) + + @staticmethod + def parse_extension_feed_item_path(path: str) -> Dict[str, str]: + """Parses a extension_feed_item path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/extensionFeedItems/(?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 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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, ExtensionFeedItemServiceTransport] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the extension feed item 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, ExtensionFeedItemServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ExtensionFeedItemServiceTransport): + # transport is a ExtensionFeedItemServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def mutate_extension_feed_items( + self, + request: Optional[ + Union[ + extension_feed_item_service.MutateExtensionFeedItemsRequest, + dict, + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[ + extension_feed_item_service.ExtensionFeedItemOperation + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> extension_feed_item_service.MutateExtensionFeedItemsResponse: + r"""Creates, updates, or removes extension feed items. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `CountryCodeError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `ExtensionFeedItemError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `ImageError <>`__ `InternalError <>`__ `LanguageCodeError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `OperationAccessDeniedError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringLengthError <>`__ `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateExtensionFeedItemsRequest, dict, None]): + The request object. Request message for + [ExtensionFeedItemService.MutateExtensionFeedItems][google.ads.googleads.v15.services.ExtensionFeedItemService.MutateExtensionFeedItems]. + customer_id (str): + Required. The ID of the customer + whose extension feed items 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.v15.services.types.ExtensionFeedItemOperation]): + Required. The list of operations to + perform on individual extension feed + items. + + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateExtensionFeedItemsResponse: + Response message for an extension + feed item 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a extension_feed_item_service.MutateExtensionFeedItemsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, extension_feed_item_service.MutateExtensionFeedItemsRequest + ): + request = ( + extension_feed_item_service.MutateExtensionFeedItemsRequest( + request + ) + ) + # 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_extension_feed_items + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ExtensionFeedItemServiceClient",) diff --git a/google/ads/googleads/v15/services/services/extension_feed_item_service/transports/__init__.py b/google/ads/googleads/v15/services/services/extension_feed_item_service/transports/__init__.py new file mode 100644 index 000000000..7df6761d7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/extension_feed_item_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 ExtensionFeedItemServiceTransport +from .grpc import ExtensionFeedItemServiceGrpcTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ExtensionFeedItemServiceTransport]] +_transport_registry["grpc"] = ExtensionFeedItemServiceGrpcTransport + +__all__ = ( + "ExtensionFeedItemServiceTransport", + "ExtensionFeedItemServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/extension_feed_item_service/transports/base.py b/google/ads/googleads/v15/services/services/extension_feed_item_service/transports/base.py new file mode 100644 index 000000000..653ee828a --- /dev/null +++ b/google/ads/googleads/v15/services/services/extension_feed_item_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import extension_feed_item_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class ExtensionFeedItemServiceTransport(abc.ABC): + """Abstract transport class for ExtensionFeedItemService.""" + + 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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_extension_feed_items: gapic_v1.method.wrap_method( + self.mutate_extension_feed_items, + 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_extension_feed_items( + self, + ) -> Callable[ + [extension_feed_item_service.MutateExtensionFeedItemsRequest], + Union[ + extension_feed_item_service.MutateExtensionFeedItemsResponse, + Awaitable[ + extension_feed_item_service.MutateExtensionFeedItemsResponse + ], + ], + ]: + raise NotImplementedError() + + +__all__ = ("ExtensionFeedItemServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/extension_feed_item_service/transports/grpc.py b/google/ads/googleads/v15/services/services/extension_feed_item_service/transports/grpc.py new file mode 100644 index 000000000..ad8ac6ac8 --- /dev/null +++ b/google/ads/googleads/v15/services/services/extension_feed_item_service/transports/grpc.py @@ -0,0 +1,287 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import extension_feed_item_service +from .base import ExtensionFeedItemServiceTransport, DEFAULT_CLIENT_INFO + + +class ExtensionFeedItemServiceGrpcTransport(ExtensionFeedItemServiceTransport): + """gRPC backend transport for ExtensionFeedItemService. + + Service to manage extension feed items. + + This 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def mutate_extension_feed_items( + self, + ) -> Callable[ + [extension_feed_item_service.MutateExtensionFeedItemsRequest], + extension_feed_item_service.MutateExtensionFeedItemsResponse, + ]: + r"""Return a callable for the mutate extension feed items method over gRPC. + + Creates, updates, or removes extension feed items. Operation + statuses are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `CountryCodeError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `ExtensionFeedItemError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `ImageError <>`__ `InternalError <>`__ `LanguageCodeError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `OperationAccessDeniedError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringLengthError <>`__ `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateExtensionFeedItemsRequest], + ~.MutateExtensionFeedItemsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_extension_feed_items" not in self._stubs: + self._stubs[ + "mutate_extension_feed_items" + ] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.ExtensionFeedItemService/MutateExtensionFeedItems", + request_serializer=extension_feed_item_service.MutateExtensionFeedItemsRequest.serialize, + response_deserializer=extension_feed_item_service.MutateExtensionFeedItemsResponse.deserialize, + ) + return self._stubs["mutate_extension_feed_items"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("ExtensionFeedItemServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/feed_item_service/__init__.py b/google/ads/googleads/v15/services/services/feed_item_service/__init__.py new file mode 100644 index 000000000..2c0f86b0b --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 FeedItemServiceClient + +__all__ = ("FeedItemServiceClient",) diff --git a/google/ads/googleads/v15/services/services/feed_item_service/client.py b/google/ads/googleads/v15/services/services/feed_item_service/client.py new file mode 100644 index 000000000..80c6ff957 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_service/client.py @@ -0,0 +1,556 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import feed_item_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import FeedItemServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import FeedItemServiceGrpcTransport + + +class FeedItemServiceClientMeta(type): + """Metaclass for the FeedItemService 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[FeedItemServiceTransport]] + _transport_registry["grpc"] = FeedItemServiceGrpcTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[FeedItemServiceTransport]: + """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 FeedItemServiceClient(metaclass=FeedItemServiceClientMeta): + """Service to manage feed items.""" + + @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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + FeedItemServiceClient: 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: + FeedItemServiceClient: 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) -> FeedItemServiceTransport: + """Returns the transport used by the client instance. + + Returns: + FeedItemServiceTransport: The transport used by the client + instance. + """ + return self._transport + + def __enter__(self) -> "FeedItemServiceClient": + 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() + + @staticmethod + def feed_path( + customer_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified feed string.""" + return "customers/{customer_id}/feeds/{feed_id}".format( + customer_id=customer_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_feed_path(path: str) -> Dict[str, str]: + """Parses a feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feeds/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_item_path( + customer_id: str, + feed_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified feed_item string.""" + return ( + "customers/{customer_id}/feedItems/{feed_id}~{feed_item_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_id=feed_item_id, + ) + ) + + @staticmethod + def parse_feed_item_path(path: str) -> Dict[str, str]: + """Parses a feed_item path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItems/(?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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, FeedItemServiceTransport]] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the feed item 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, FeedItemServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, FeedItemServiceTransport): + # transport is a FeedItemServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def mutate_feed_items( + self, + request: Optional[ + Union[feed_item_service.MutateFeedItemsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[feed_item_service.FeedItemOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> feed_item_service.MutateFeedItemsResponse: + r"""Creates, updates, or removes feed items. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `CriterionError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FeedItemError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NotEmptyError <>`__ `NullError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateFeedItemsRequest, dict, None]): + The request object. Request message for + [FeedItemService.MutateFeedItems][google.ads.googleads.v15.services.FeedItemService.MutateFeedItems]. + customer_id (str): + Required. The ID of the customer + whose feed items 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.v15.services.types.FeedItemOperation]): + Required. The list of operations to + perform on individual feed items. + + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateFeedItemsResponse: + Response message for an feed item + 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a feed_item_service.MutateFeedItemsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, feed_item_service.MutateFeedItemsRequest): + request = feed_item_service.MutateFeedItemsRequest(request) + # 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_feed_items + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("FeedItemServiceClient",) diff --git a/google/ads/googleads/v15/services/services/feed_item_service/transports/__init__.py b/google/ads/googleads/v15/services/services/feed_item_service/transports/__init__.py new file mode 100644 index 000000000..0cddf3002 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 FeedItemServiceTransport +from .grpc import FeedItemServiceGrpcTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[FeedItemServiceTransport]] +_transport_registry["grpc"] = FeedItemServiceGrpcTransport + +__all__ = ( + "FeedItemServiceTransport", + "FeedItemServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/feed_item_service/transports/base.py b/google/ads/googleads/v15/services/services/feed_item_service/transports/base.py new file mode 100644 index 000000000..57b952933 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import feed_item_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class FeedItemServiceTransport(abc.ABC): + """Abstract transport class for FeedItemService.""" + + 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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_feed_items: gapic_v1.method.wrap_method( + self.mutate_feed_items, + 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_feed_items( + self, + ) -> Callable[ + [feed_item_service.MutateFeedItemsRequest], + Union[ + feed_item_service.MutateFeedItemsResponse, + Awaitable[feed_item_service.MutateFeedItemsResponse], + ], + ]: + raise NotImplementedError() + + +__all__ = ("FeedItemServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/feed_item_service/transports/grpc.py b/google/ads/googleads/v15/services/services/feed_item_service/transports/grpc.py new file mode 100644 index 000000000..bf4e68842 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_service/transports/grpc.py @@ -0,0 +1,286 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import feed_item_service +from .base import FeedItemServiceTransport, DEFAULT_CLIENT_INFO + + +class FeedItemServiceGrpcTransport(FeedItemServiceTransport): + """gRPC backend transport for FeedItemService. + + Service to manage feed items. + + This 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def mutate_feed_items( + self, + ) -> Callable[ + [feed_item_service.MutateFeedItemsRequest], + feed_item_service.MutateFeedItemsResponse, + ]: + r"""Return a callable for the mutate feed items method over gRPC. + + Creates, updates, or removes feed items. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `CriterionError <>`__ `DatabaseError <>`__ `DateError <>`__ + `DistinctError <>`__ `FeedItemError <>`__ `FieldError <>`__ + `FieldMaskError <>`__ `HeaderError <>`__ `IdError <>`__ + `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NotEmptyError <>`__ `NullError <>`__ + `OperatorError <>`__ `QuotaError <>`__ `RangeError <>`__ + `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + `UrlFieldError <>`__ + + Returns: + Callable[[~.MutateFeedItemsRequest], + ~.MutateFeedItemsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_feed_items" not in self._stubs: + self._stubs["mutate_feed_items"] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.FeedItemService/MutateFeedItems", + request_serializer=feed_item_service.MutateFeedItemsRequest.serialize, + response_deserializer=feed_item_service.MutateFeedItemsResponse.deserialize, + ) + return self._stubs["mutate_feed_items"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("FeedItemServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/feed_item_set_link_service/__init__.py b/google/ads/googleads/v15/services/services/feed_item_set_link_service/__init__.py new file mode 100644 index 000000000..b69a80884 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_set_link_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 FeedItemSetLinkServiceClient + +__all__ = ("FeedItemSetLinkServiceClient",) diff --git a/google/ads/googleads/v15/services/services/feed_item_set_link_service/client.py b/google/ads/googleads/v15/services/services/feed_item_set_link_service/client.py new file mode 100644 index 000000000..944c4f7e5 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_set_link_service/client.py @@ -0,0 +1,585 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import feed_item_set_link_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import ( + FeedItemSetLinkServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import FeedItemSetLinkServiceGrpcTransport + + +class FeedItemSetLinkServiceClientMeta(type): + """Metaclass for the FeedItemSetLinkService 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[FeedItemSetLinkServiceTransport]] + _transport_registry["grpc"] = FeedItemSetLinkServiceGrpcTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[FeedItemSetLinkServiceTransport]: + """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 FeedItemSetLinkServiceClient(metaclass=FeedItemSetLinkServiceClientMeta): + """Service to manage feed item set 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + FeedItemSetLinkServiceClient: 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: + FeedItemSetLinkServiceClient: 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) -> FeedItemSetLinkServiceTransport: + """Returns the transport used by the client instance. + + Returns: + FeedItemSetLinkServiceTransport: The transport used by the client + instance. + """ + return self._transport + + def __enter__(self) -> "FeedItemSetLinkServiceClient": + 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() + + @staticmethod + def feed_item_path( + customer_id: str, + feed_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified feed_item string.""" + return ( + "customers/{customer_id}/feedItems/{feed_id}~{feed_item_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_id=feed_item_id, + ) + ) + + @staticmethod + def parse_feed_item_path(path: str) -> Dict[str, str]: + """Parses a feed_item path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItems/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_item_set_path( + customer_id: str, + feed_id: str, + feed_item_set_id: str, + ) -> str: + """Returns a fully-qualified feed_item_set string.""" + return "customers/{customer_id}/feedItemSets/{feed_id}~{feed_item_set_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_set_id=feed_item_set_id, + ) + + @staticmethod + def parse_feed_item_set_path(path: str) -> Dict[str, str]: + """Parses a feed_item_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItemSets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_item_set_link_path( + customer_id: str, + feed_id: str, + feed_item_set_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified feed_item_set_link string.""" + return "customers/{customer_id}/feedItemSetLinks/{feed_id}~{feed_item_set_id}~{feed_item_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_set_id=feed_item_set_id, + feed_item_id=feed_item_id, + ) + + @staticmethod + def parse_feed_item_set_link_path(path: str) -> Dict[str, str]: + """Parses a feed_item_set_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItemSetLinks/(?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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, FeedItemSetLinkServiceTransport]] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the feed item set 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, FeedItemSetLinkServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, FeedItemSetLinkServiceTransport): + # transport is a FeedItemSetLinkServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def mutate_feed_item_set_links( + self, + request: Optional[ + Union[ + feed_item_set_link_service.MutateFeedItemSetLinksRequest, dict + ] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[feed_item_set_link_service.FeedItemSetLinkOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> feed_item_set_link_service.MutateFeedItemSetLinksResponse: + r"""Creates, updates, or removes feed item set links. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateFeedItemSetLinksRequest, dict, None]): + The request object. Request message for + [FeedItemSetLinkService.MutateFeedItemSetLinks][google.ads.googleads.v15.services.FeedItemSetLinkService.MutateFeedItemSetLinks]. + customer_id (str): + Required. The ID of the customer + whose feed item set 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.v15.services.types.FeedItemSetLinkOperation]): + Required. The list of operations to + perform on individual feed item set + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateFeedItemSetLinksResponse: + Response message for a feed item set + 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a feed_item_set_link_service.MutateFeedItemSetLinksRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, feed_item_set_link_service.MutateFeedItemSetLinksRequest + ): + request = feed_item_set_link_service.MutateFeedItemSetLinksRequest( + request + ) + # 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_feed_item_set_links + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("FeedItemSetLinkServiceClient",) diff --git a/google/ads/googleads/v15/services/services/feed_item_set_link_service/transports/__init__.py b/google/ads/googleads/v15/services/services/feed_item_set_link_service/transports/__init__.py new file mode 100644 index 000000000..7000820d2 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_set_link_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 FeedItemSetLinkServiceTransport +from .grpc import FeedItemSetLinkServiceGrpcTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[FeedItemSetLinkServiceTransport]] +_transport_registry["grpc"] = FeedItemSetLinkServiceGrpcTransport + +__all__ = ( + "FeedItemSetLinkServiceTransport", + "FeedItemSetLinkServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/feed_item_set_link_service/transports/base.py b/google/ads/googleads/v15/services/services/feed_item_set_link_service/transports/base.py new file mode 100644 index 000000000..936f2cbc3 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_set_link_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import feed_item_set_link_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class FeedItemSetLinkServiceTransport(abc.ABC): + """Abstract transport class for FeedItemSetLinkService.""" + + 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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_feed_item_set_links: gapic_v1.method.wrap_method( + self.mutate_feed_item_set_links, + 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_feed_item_set_links( + self, + ) -> Callable[ + [feed_item_set_link_service.MutateFeedItemSetLinksRequest], + Union[ + feed_item_set_link_service.MutateFeedItemSetLinksResponse, + Awaitable[ + feed_item_set_link_service.MutateFeedItemSetLinksResponse + ], + ], + ]: + raise NotImplementedError() + + +__all__ = ("FeedItemSetLinkServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/feed_item_set_link_service/transports/grpc.py b/google/ads/googleads/v15/services/services/feed_item_set_link_service/transports/grpc.py new file mode 100644 index 000000000..772a0cc7b --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_set_link_service/transports/grpc.py @@ -0,0 +1,279 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import feed_item_set_link_service +from .base import FeedItemSetLinkServiceTransport, DEFAULT_CLIENT_INFO + + +class FeedItemSetLinkServiceGrpcTransport(FeedItemSetLinkServiceTransport): + """gRPC backend transport for FeedItemSetLinkService. + + Service to manage feed item set 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def mutate_feed_item_set_links( + self, + ) -> Callable[ + [feed_item_set_link_service.MutateFeedItemSetLinksRequest], + feed_item_set_link_service.MutateFeedItemSetLinksResponse, + ]: + r"""Return a callable for the mutate feed item set links method over gRPC. + + Creates, updates, or removes feed item set links. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ `RequestError <>`__ + + Returns: + Callable[[~.MutateFeedItemSetLinksRequest], + ~.MutateFeedItemSetLinksResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_feed_item_set_links" not in self._stubs: + self._stubs[ + "mutate_feed_item_set_links" + ] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.FeedItemSetLinkService/MutateFeedItemSetLinks", + request_serializer=feed_item_set_link_service.MutateFeedItemSetLinksRequest.serialize, + response_deserializer=feed_item_set_link_service.MutateFeedItemSetLinksResponse.deserialize, + ) + return self._stubs["mutate_feed_item_set_links"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("FeedItemSetLinkServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/feed_item_set_service/__init__.py b/google/ads/googleads/v15/services/services/feed_item_set_service/__init__.py new file mode 100644 index 000000000..49a3d28ae --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_set_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 FeedItemSetServiceClient + +__all__ = ("FeedItemSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/feed_item_set_service/client.py b/google/ads/googleads/v15/services/services/feed_item_set_service/client.py new file mode 100644 index 000000000..22ebea8cc --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_set_service/client.py @@ -0,0 +1,549 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import feed_item_set_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import FeedItemSetServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import FeedItemSetServiceGrpcTransport + + +class FeedItemSetServiceClientMeta(type): + """Metaclass for the FeedItemSetService 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[FeedItemSetServiceTransport]] + _transport_registry["grpc"] = FeedItemSetServiceGrpcTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[FeedItemSetServiceTransport]: + """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 FeedItemSetServiceClient(metaclass=FeedItemSetServiceClientMeta): + """Service to manage feed Item 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + FeedItemSetServiceClient: 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: + FeedItemSetServiceClient: 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) -> FeedItemSetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + FeedItemSetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + def __enter__(self) -> "FeedItemSetServiceClient": + 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() + + @staticmethod + def feed_path( + customer_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified feed string.""" + return "customers/{customer_id}/feeds/{feed_id}".format( + customer_id=customer_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_feed_path(path: str) -> Dict[str, str]: + """Parses a feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feeds/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_item_set_path( + customer_id: str, + feed_id: str, + feed_item_set_id: str, + ) -> str: + """Returns a fully-qualified feed_item_set string.""" + return "customers/{customer_id}/feedItemSets/{feed_id}~{feed_item_set_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_set_id=feed_item_set_id, + ) + + @staticmethod + def parse_feed_item_set_path(path: str) -> Dict[str, str]: + """Parses a feed_item_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItemSets/(?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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, FeedItemSetServiceTransport]] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the feed item 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, FeedItemSetServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, FeedItemSetServiceTransport): + # transport is a FeedItemSetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def mutate_feed_item_sets( + self, + request: Optional[ + Union[feed_item_set_service.MutateFeedItemSetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[feed_item_set_service.FeedItemSetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> feed_item_set_service.MutateFeedItemSetsResponse: + r"""Creates, updates or removes feed item sets. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateFeedItemSetsRequest, dict, None]): + The request object. Request message for + [FeedItemSetService.MutateFeedItemSets][google.ads.googleads.v15.services.FeedItemSetService.MutateFeedItemSets]. + customer_id (str): + Required. The ID of the customer + whose feed item 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.v15.services.types.FeedItemSetOperation]): + Required. The list of operations to + perform on individual feed item 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateFeedItemSetsResponse: + Response message for an feed item 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a feed_item_set_service.MutateFeedItemSetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, feed_item_set_service.MutateFeedItemSetsRequest + ): + request = feed_item_set_service.MutateFeedItemSetsRequest(request) + # 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_feed_item_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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("FeedItemSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/feed_item_set_service/transports/__init__.py b/google/ads/googleads/v15/services/services/feed_item_set_service/transports/__init__.py new file mode 100644 index 000000000..fb47534b8 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_set_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 FeedItemSetServiceTransport +from .grpc import FeedItemSetServiceGrpcTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[FeedItemSetServiceTransport]] +_transport_registry["grpc"] = FeedItemSetServiceGrpcTransport + +__all__ = ( + "FeedItemSetServiceTransport", + "FeedItemSetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/feed_item_set_service/transports/base.py b/google/ads/googleads/v15/services/services/feed_item_set_service/transports/base.py new file mode 100644 index 000000000..5cb599578 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_set_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import feed_item_set_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class FeedItemSetServiceTransport(abc.ABC): + """Abstract transport class for FeedItemSetService.""" + + 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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_feed_item_sets: gapic_v1.method.wrap_method( + self.mutate_feed_item_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_feed_item_sets( + self, + ) -> Callable[ + [feed_item_set_service.MutateFeedItemSetsRequest], + Union[ + feed_item_set_service.MutateFeedItemSetsResponse, + Awaitable[feed_item_set_service.MutateFeedItemSetsResponse], + ], + ]: + raise NotImplementedError() + + +__all__ = ("FeedItemSetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/feed_item_set_service/transports/grpc.py b/google/ads/googleads/v15/services/services/feed_item_set_service/transports/grpc.py new file mode 100644 index 000000000..2e731ff52 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_set_service/transports/grpc.py @@ -0,0 +1,281 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import feed_item_set_service +from .base import FeedItemSetServiceTransport, DEFAULT_CLIENT_INFO + + +class FeedItemSetServiceGrpcTransport(FeedItemSetServiceTransport): + """gRPC backend transport for FeedItemSetService. + + Service to manage feed Item 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def mutate_feed_item_sets( + self, + ) -> Callable[ + [feed_item_set_service.MutateFeedItemSetsRequest], + feed_item_set_service.MutateFeedItemSetsResponse, + ]: + r"""Return a callable for the mutate feed item sets method over gRPC. + + Creates, updates or removes feed item sets. Operation statuses + are returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `MutateError <>`__ `QuotaError <>`__ + `RequestError <>`__ + + Returns: + Callable[[~.MutateFeedItemSetsRequest], + ~.MutateFeedItemSetsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_feed_item_sets" not in self._stubs: + self._stubs[ + "mutate_feed_item_sets" + ] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.FeedItemSetService/MutateFeedItemSets", + request_serializer=feed_item_set_service.MutateFeedItemSetsRequest.serialize, + response_deserializer=feed_item_set_service.MutateFeedItemSetsResponse.deserialize, + ) + return self._stubs["mutate_feed_item_sets"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("FeedItemSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/feed_item_target_service/__init__.py b/google/ads/googleads/v15/services/services/feed_item_target_service/__init__.py new file mode 100644 index 000000000..0fceb3374 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_target_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 FeedItemTargetServiceClient + +__all__ = ("FeedItemTargetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/feed_item_target_service/client.py b/google/ads/googleads/v15/services/services/feed_item_target_service/client.py new file mode 100644 index 000000000..3167fe15a --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_target_service/client.py @@ -0,0 +1,620 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import feed_item_target_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import FeedItemTargetServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import FeedItemTargetServiceGrpcTransport + + +class FeedItemTargetServiceClientMeta(type): + """Metaclass for the FeedItemTargetService 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[FeedItemTargetServiceTransport]] + _transport_registry["grpc"] = FeedItemTargetServiceGrpcTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[FeedItemTargetServiceTransport]: + """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 FeedItemTargetServiceClient(metaclass=FeedItemTargetServiceClientMeta): + """Service to manage feed item targets.""" + + @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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + FeedItemTargetServiceClient: 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: + FeedItemTargetServiceClient: 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) -> FeedItemTargetServiceTransport: + """Returns the transport used by the client instance. + + Returns: + FeedItemTargetServiceTransport: The transport used by the client + instance. + """ + return self._transport + + def __enter__(self) -> "FeedItemTargetServiceClient": + 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() + + @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 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 feed_item_path( + customer_id: str, + feed_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified feed_item string.""" + return ( + "customers/{customer_id}/feedItems/{feed_id}~{feed_item_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_id=feed_item_id, + ) + ) + + @staticmethod + def parse_feed_item_path(path: str) -> Dict[str, str]: + """Parses a feed_item path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItems/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_item_target_path( + customer_id: str, + feed_id: str, + feed_item_id: str, + feed_item_target_type: str, + feed_item_target_id: str, + ) -> str: + """Returns a fully-qualified feed_item_target string.""" + return "customers/{customer_id}/feedItemTargets/{feed_id}~{feed_item_id}~{feed_item_target_type}~{feed_item_target_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_id=feed_item_id, + feed_item_target_type=feed_item_target_type, + feed_item_target_id=feed_item_target_id, + ) + + @staticmethod + def parse_feed_item_target_path(path: str) -> Dict[str, str]: + """Parses a feed_item_target path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItemTargets/(?P.+?)~(?P.+?)~(?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 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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, FeedItemTargetServiceTransport]] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the feed item target 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, FeedItemTargetServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, FeedItemTargetServiceTransport): + # transport is a FeedItemTargetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def mutate_feed_item_targets( + self, + request: Optional[ + Union[feed_item_target_service.MutateFeedItemTargetsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[feed_item_target_service.FeedItemTargetOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> feed_item_target_service.MutateFeedItemTargetsResponse: + r"""Creates or removes feed item targets. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ + `FeedItemTargetError <>`__ `FieldError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `MutateError <>`__ + `NotEmptyError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateFeedItemTargetsRequest, dict, None]): + The request object. Request message for + [FeedItemTargetService.MutateFeedItemTargets][google.ads.googleads.v15.services.FeedItemTargetService.MutateFeedItemTargets]. + customer_id (str): + Required. The ID of the customer + whose feed item targets 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.v15.services.types.FeedItemTargetOperation]): + Required. The list of operations to + perform on individual feed item targets. + + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateFeedItemTargetsResponse: + Response message for an feed item + target 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a feed_item_target_service.MutateFeedItemTargetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, feed_item_target_service.MutateFeedItemTargetsRequest + ): + request = feed_item_target_service.MutateFeedItemTargetsRequest( + request + ) + # 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_feed_item_targets + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("FeedItemTargetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/feed_item_target_service/transports/__init__.py b/google/ads/googleads/v15/services/services/feed_item_target_service/transports/__init__.py new file mode 100644 index 000000000..393827200 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_target_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 FeedItemTargetServiceTransport +from .grpc import FeedItemTargetServiceGrpcTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[FeedItemTargetServiceTransport]] +_transport_registry["grpc"] = FeedItemTargetServiceGrpcTransport + +__all__ = ( + "FeedItemTargetServiceTransport", + "FeedItemTargetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/feed_item_target_service/transports/base.py b/google/ads/googleads/v15/services/services/feed_item_target_service/transports/base.py new file mode 100644 index 000000000..d05a91a1f --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_target_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import feed_item_target_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class FeedItemTargetServiceTransport(abc.ABC): + """Abstract transport class for FeedItemTargetService.""" + + 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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_feed_item_targets: gapic_v1.method.wrap_method( + self.mutate_feed_item_targets, + 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_feed_item_targets( + self, + ) -> Callable[ + [feed_item_target_service.MutateFeedItemTargetsRequest], + Union[ + feed_item_target_service.MutateFeedItemTargetsResponse, + Awaitable[feed_item_target_service.MutateFeedItemTargetsResponse], + ], + ]: + raise NotImplementedError() + + +__all__ = ("FeedItemTargetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/feed_item_target_service/transports/grpc.py b/google/ads/googleads/v15/services/services/feed_item_target_service/transports/grpc.py new file mode 100644 index 000000000..a3a5941d2 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_item_target_service/transports/grpc.py @@ -0,0 +1,285 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import feed_item_target_service +from .base import FeedItemTargetServiceTransport, DEFAULT_CLIENT_INFO + + +class FeedItemTargetServiceGrpcTransport(FeedItemTargetServiceTransport): + """gRPC backend transport for FeedItemTargetService. + + Service to manage feed item targets. + + This 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def mutate_feed_item_targets( + self, + ) -> Callable[ + [feed_item_target_service.MutateFeedItemTargetsRequest], + feed_item_target_service.MutateFeedItemTargetsResponse, + ]: + r"""Return a callable for the mutate feed item targets method over gRPC. + + Creates or removes feed item targets. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CriterionError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ + `FeedItemTargetError <>`__ `FieldError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `MutateError <>`__ + `NotEmptyError <>`__ `OperatorError <>`__ `QuotaError <>`__ + `RangeError <>`__ `RequestError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateFeedItemTargetsRequest], + ~.MutateFeedItemTargetsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_feed_item_targets" not in self._stubs: + self._stubs[ + "mutate_feed_item_targets" + ] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.FeedItemTargetService/MutateFeedItemTargets", + request_serializer=feed_item_target_service.MutateFeedItemTargetsRequest.serialize, + response_deserializer=feed_item_target_service.MutateFeedItemTargetsResponse.deserialize, + ) + return self._stubs["mutate_feed_item_targets"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("FeedItemTargetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/feed_mapping_service/__init__.py b/google/ads/googleads/v15/services/services/feed_mapping_service/__init__.py new file mode 100644 index 000000000..86072d824 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_mapping_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 FeedMappingServiceClient + +__all__ = ("FeedMappingServiceClient",) diff --git a/google/ads/googleads/v15/services/services/feed_mapping_service/client.py b/google/ads/googleads/v15/services/services/feed_mapping_service/client.py new file mode 100644 index 000000000..1b1c95c7a --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_mapping_service/client.py @@ -0,0 +1,554 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import feed_mapping_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import FeedMappingServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import FeedMappingServiceGrpcTransport + + +class FeedMappingServiceClientMeta(type): + """Metaclass for the FeedMappingService 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[FeedMappingServiceTransport]] + _transport_registry["grpc"] = FeedMappingServiceGrpcTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[FeedMappingServiceTransport]: + """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 FeedMappingServiceClient(metaclass=FeedMappingServiceClientMeta): + """Service to manage feed mappings.""" + + @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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + FeedMappingServiceClient: 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: + FeedMappingServiceClient: 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) -> FeedMappingServiceTransport: + """Returns the transport used by the client instance. + + Returns: + FeedMappingServiceTransport: The transport used by the client + instance. + """ + return self._transport + + def __enter__(self) -> "FeedMappingServiceClient": + 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() + + @staticmethod + def feed_path( + customer_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified feed string.""" + return "customers/{customer_id}/feeds/{feed_id}".format( + customer_id=customer_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_feed_path(path: str) -> Dict[str, str]: + """Parses a feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feeds/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_mapping_path( + customer_id: str, + feed_id: str, + feed_mapping_id: str, + ) -> str: + """Returns a fully-qualified feed_mapping string.""" + return "customers/{customer_id}/feedMappings/{feed_id}~{feed_mapping_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_mapping_id=feed_mapping_id, + ) + + @staticmethod + def parse_feed_mapping_path(path: str) -> Dict[str, str]: + """Parses a feed_mapping path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedMappings/(?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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, FeedMappingServiceTransport]] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the feed mapping 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, FeedMappingServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, FeedMappingServiceTransport): + # transport is a FeedMappingServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def mutate_feed_mappings( + self, + request: Optional[ + Union[feed_mapping_service.MutateFeedMappingsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[feed_mapping_service.FeedMappingOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> feed_mapping_service.MutateFeedMappingsResponse: + r"""Creates or removes feed mappings. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FeedMappingError <>`__ `FieldError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NotEmptyError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateFeedMappingsRequest, dict, None]): + The request object. Request message for + [FeedMappingService.MutateFeedMappings][google.ads.googleads.v15.services.FeedMappingService.MutateFeedMappings]. + customer_id (str): + Required. The ID of the customer + whose feed mappings 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.v15.services.types.FeedMappingOperation]): + Required. The list of operations to + perform on individual feed mappings. + + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateFeedMappingsResponse: + Response message for a feed mapping + 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a feed_mapping_service.MutateFeedMappingsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, feed_mapping_service.MutateFeedMappingsRequest + ): + request = feed_mapping_service.MutateFeedMappingsRequest(request) + # 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_feed_mappings + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("FeedMappingServiceClient",) diff --git a/google/ads/googleads/v15/services/services/feed_mapping_service/transports/__init__.py b/google/ads/googleads/v15/services/services/feed_mapping_service/transports/__init__.py new file mode 100644 index 000000000..a4ae99d73 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_mapping_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 FeedMappingServiceTransport +from .grpc import FeedMappingServiceGrpcTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[FeedMappingServiceTransport]] +_transport_registry["grpc"] = FeedMappingServiceGrpcTransport + +__all__ = ( + "FeedMappingServiceTransport", + "FeedMappingServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/feed_mapping_service/transports/base.py b/google/ads/googleads/v15/services/services/feed_mapping_service/transports/base.py new file mode 100644 index 000000000..6c8b4c459 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_mapping_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import feed_mapping_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class FeedMappingServiceTransport(abc.ABC): + """Abstract transport class for FeedMappingService.""" + + 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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_feed_mappings: gapic_v1.method.wrap_method( + self.mutate_feed_mappings, + 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_feed_mappings( + self, + ) -> Callable[ + [feed_mapping_service.MutateFeedMappingsRequest], + Union[ + feed_mapping_service.MutateFeedMappingsResponse, + Awaitable[feed_mapping_service.MutateFeedMappingsResponse], + ], + ]: + raise NotImplementedError() + + +__all__ = ("FeedMappingServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/feed_mapping_service/transports/grpc.py b/google/ads/googleads/v15/services/services/feed_mapping_service/transports/grpc.py new file mode 100644 index 000000000..d29cbd162 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_mapping_service/transports/grpc.py @@ -0,0 +1,284 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import feed_mapping_service +from .base import FeedMappingServiceTransport, DEFAULT_CLIENT_INFO + + +class FeedMappingServiceGrpcTransport(FeedMappingServiceTransport): + """gRPC backend transport for FeedMappingService. + + Service to manage feed mappings. + + This 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def mutate_feed_mappings( + self, + ) -> Callable[ + [feed_mapping_service.MutateFeedMappingsRequest], + feed_mapping_service.MutateFeedMappingsResponse, + ]: + r"""Return a callable for the mutate feed mappings method over gRPC. + + Creates or removes feed mappings. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `DatabaseError <>`__ + `DistinctError <>`__ `FeedMappingError <>`__ `FieldError <>`__ + `HeaderError <>`__ `IdError <>`__ `InternalError <>`__ + `MutateError <>`__ `NotEmptyError <>`__ + `OperationAccessDeniedError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `SizeLimitError <>`__ `StringFormatError <>`__ + `StringLengthError <>`__ + + Returns: + Callable[[~.MutateFeedMappingsRequest], + ~.MutateFeedMappingsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_feed_mappings" not in self._stubs: + self._stubs["mutate_feed_mappings"] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.FeedMappingService/MutateFeedMappings", + request_serializer=feed_mapping_service.MutateFeedMappingsRequest.serialize, + response_deserializer=feed_mapping_service.MutateFeedMappingsResponse.deserialize, + ) + return self._stubs["mutate_feed_mappings"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("FeedMappingServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/feed_service/__init__.py b/google/ads/googleads/v15/services/services/feed_service/__init__.py new file mode 100644 index 000000000..2e199491c --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 FeedServiceClient + +__all__ = ("FeedServiceClient",) diff --git a/google/ads/googleads/v15/services/services/feed_service/client.py b/google/ads/googleads/v15/services/services/feed_service/client.py new file mode 100644 index 000000000..adf20fb28 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_service/client.py @@ -0,0 +1,525 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import feed_service +from google.rpc import status_pb2 # type: ignore +from .transports.base import FeedServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import FeedServiceGrpcTransport + + +class FeedServiceClientMeta(type): + """Metaclass for the FeedService 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[FeedServiceTransport]] + _transport_registry["grpc"] = FeedServiceGrpcTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[FeedServiceTransport]: + """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 FeedServiceClient(metaclass=FeedServiceClientMeta): + """Service to manage feeds.""" + + @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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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: + FeedServiceClient: 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: + FeedServiceClient: 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) -> FeedServiceTransport: + """Returns the transport used by the client instance. + + Returns: + FeedServiceTransport: The transport used by the client + instance. + """ + return self._transport + + def __enter__(self) -> "FeedServiceClient": + 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() + + @staticmethod + def feed_path( + customer_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified feed string.""" + return "customers/{customer_id}/feeds/{feed_id}".format( + customer_id=customer_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_feed_path(path: str) -> Dict[str, str]: + """Parses a feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feeds/(?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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, FeedServiceTransport]] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the feed 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, FeedServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, FeedServiceTransport): + # transport is a FeedServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + def mutate_feeds( + self, + request: Optional[Union[feed_service.MutateFeedsRequest, dict]] = None, + *, + customer_id: Optional[str] = None, + operations: Optional[ + MutableSequence[feed_service.FeedOperation] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> feed_service.MutateFeedsResponse: + r"""Creates, updates, or removes feeds. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FeedError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateFeedsRequest, dict, None]): + The request object. Request message for + [FeedService.MutateFeeds][google.ads.googleads.v15.services.FeedService.MutateFeeds]. + customer_id (str): + Required. The ID of the customer + whose feeds 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.v15.services.types.FeedOperation]): + Required. The list of operations to + perform on individual feeds. + + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateFeedsResponse: + Response message for an feed 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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a feed_service.MutateFeedsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, feed_service.MutateFeedsRequest): + request = feed_service.MutateFeedsRequest(request) + # 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_feeds] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("FeedServiceClient",) diff --git a/google/ads/googleads/v15/services/services/feed_service/transports/__init__.py b/google/ads/googleads/v15/services/services/feed_service/transports/__init__.py new file mode 100644 index 000000000..8db0f0412 --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 FeedServiceTransport +from .grpc import FeedServiceGrpcTransport + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[FeedServiceTransport]] +_transport_registry["grpc"] = FeedServiceGrpcTransport + +__all__ = ( + "FeedServiceTransport", + "FeedServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/feed_service/transports/base.py b/google/ads/googleads/v15/services/services/feed_service/transports/base.py new file mode 100644 index 000000000..d8cbb30ee --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import feed_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +class FeedServiceTransport(abc.ABC): + """Abstract transport class for FeedService.""" + + 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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.mutate_feeds: gapic_v1.method.wrap_method( + self.mutate_feeds, + 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_feeds( + self, + ) -> Callable[ + [feed_service.MutateFeedsRequest], + Union[ + feed_service.MutateFeedsResponse, + Awaitable[feed_service.MutateFeedsResponse], + ], + ]: + raise NotImplementedError() + + +__all__ = ("FeedServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/feed_service/transports/grpc.py b/google/ads/googleads/v15/services/services/feed_service/transports/grpc.py new file mode 100644 index 000000000..145fb7ead --- /dev/null +++ b/google/ads/googleads/v15/services/services/feed_service/transports/grpc.py @@ -0,0 +1,284 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import feed_service +from .base import FeedServiceTransport, DEFAULT_CLIENT_INFO + + +class FeedServiceGrpcTransport(FeedServiceTransport): + """gRPC backend transport for FeedService. + + Service to manage feeds. + + This 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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def mutate_feeds( + self, + ) -> Callable[ + [feed_service.MutateFeedsRequest], feed_service.MutateFeedsResponse + ]: + r"""Return a callable for the mutate feeds method over gRPC. + + Creates, updates, or removes feeds. Operation statuses are + returned. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `CollectionSizeError <>`__ + `DatabaseError <>`__ `DistinctError <>`__ `FeedError <>`__ + `FieldError <>`__ `FieldMaskError <>`__ `HeaderError <>`__ + `IdError <>`__ `InternalError <>`__ `ListOperationError <>`__ + `MutateError <>`__ `NewResourceCreationError <>`__ + `NotEmptyError <>`__ `NullError <>`__ `OperatorError <>`__ + `QuotaError <>`__ `RangeError <>`__ `RequestError <>`__ + `ResourceCountLimitExceededError <>`__ `SizeLimitError <>`__ + `StringFormatError <>`__ `StringLengthError <>`__ + + Returns: + Callable[[~.MutateFeedsRequest], + ~.MutateFeedsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-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_feeds" not in self._stubs: + self._stubs["mutate_feeds"] = self.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.FeedService/MutateFeeds", + request_serializer=feed_service.MutateFeedsRequest.serialize, + response_deserializer=feed_service.MutateFeedsResponse.deserialize, + ) + return self._stubs["mutate_feeds"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("FeedServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/geo_target_constant_service/__init__.py b/google/ads/googleads/v15/services/services/geo_target_constant_service/__init__.py new file mode 100644 index 000000000..5af9928d4 --- /dev/null +++ b/google/ads/googleads/v15/services/services/geo_target_constant_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("GeoTargetConstantServiceClient",) diff --git a/google/ads/googleads/v15/services/services/geo_target_constant_service/client.py b/google/ads/googleads/v15/services/services/geo_target_constant_service/client.py new file mode 100644 index 000000000..afd2051c2 --- /dev/null +++ b/google/ads/googleads/v15/services/services/geo_target_constant_service/client.py @@ -0,0 +1,487 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import geo_target_constant_service +from .transports.base import ( + GeoTargetConstantServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import GeoTargetConstantServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, GeoTargetConstantServiceTransport): + # transport is a GeoTargetConstantServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.SuggestGeoTargetConstantsRequest, dict, None]): + The request object. Request message for + [GeoTargetConstantService.SuggestGeoTargetConstants][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.SuggestGeoTargetConstantsResponse: + Response message for + [GeoTargetConstantService.SuggestGeoTargetConstants][google.ads.googleads.v15.services.GeoTargetConstantService.SuggestGeoTargetConstants]. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a geo_target_constant_service.SuggestGeoTargetConstantsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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 + ] + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("GeoTargetConstantServiceClient",) diff --git a/google/ads/googleads/v15/services/services/geo_target_constant_service/transports/__init__.py b/google/ads/googleads/v15/services/services/geo_target_constant_service/transports/__init__.py new file mode 100644 index 000000000..7cca14f45 --- /dev/null +++ b/google/ads/googleads/v15/services/services/geo_target_constant_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[GeoTargetConstantServiceTransport]] +_transport_registry["grpc"] = GeoTargetConstantServiceGrpcTransport + +__all__ = ( + "GeoTargetConstantServiceTransport", + "GeoTargetConstantServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/geo_target_constant_service/transports/base.py b/google/ads/googleads/v15/services/services/geo_target_constant_service/transports/base.py new file mode 100644 index 000000000..dd25b52f3 --- /dev/null +++ b/google/ads/googleads/v15/services/services/geo_target_constant_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import geo_target_constant_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("GeoTargetConstantServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/geo_target_constant_service/transports/grpc.py b/google/ads/googleads/v15/services/services/geo_target_constant_service/transports/grpc.py new file mode 100644 index 000000000..a1450b50b --- /dev/null +++ b/google/ads/googleads/v15/services/services/geo_target_constant_service/transports/grpc.py @@ -0,0 +1,281 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import geo_target_constant_service +from .base import GeoTargetConstantServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("GeoTargetConstantServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/google_ads_field_service/__init__.py b/google/ads/googleads/v15/services/services/google_ads_field_service/__init__.py new file mode 100644 index 000000000..ea53b0e5a --- /dev/null +++ b/google/ads/googleads/v15/services/services/google_ads_field_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("GoogleAdsFieldServiceClient",) diff --git a/google/ads/googleads/v15/services/services/google_ads_field_service/client.py b/google/ads/googleads/v15/services/services/google_ads_field_service/client.py new file mode 100644 index 000000000..eea7ba493 --- /dev/null +++ b/google/ads/googleads/v15/services/services/google_ads_field_service/client.py @@ -0,0 +1,596 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.resources.types import google_ads_field +from google.ads.googleads.v15.services.services.google_ads_field_service import ( + pagers, +) +from google.ads.googleads.v15.services.types import google_ads_field_service +from .transports.base import GoogleAdsFieldServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import GoogleAdsFieldServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, GoogleAdsFieldServiceTransport): + # transport is a GoogleAdsFieldServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.GetGoogleAdsFieldRequest, dict, None]): + The request object. Request message for + [GoogleAdsFieldService.GetGoogleAdsField][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([resource_name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a google_ads_field_service.GetGoogleAdsFieldRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.SearchGoogleAdsFieldsRequest, dict, None]): + The request object. Request message for + [GoogleAdsFieldService.SearchGoogleAdsFields][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.services.google_ads_field_service.pagers.SearchGoogleAdsFieldsPager: + Response message for + [GoogleAdsFieldService.SearchGoogleAdsFields][google.ads.googleads.v15.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. + has_flattened_params = any([query]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a google_ads_field_service.SearchGoogleAdsFieldsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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 + ] + + # 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, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("GoogleAdsFieldServiceClient",) diff --git a/google/ads/googleads/v15/services/services/google_ads_field_service/pagers.py b/google/ads/googleads/v15/services/services/google_ads_field_service/pagers.py new file mode 100644 index 000000000..bea0900d5 --- /dev/null +++ b/google/ads/googleads/v15/services/services/google_ads_field_service/pagers.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Any, Callable, Iterable, Iterator, Sequence, Tuple + +from google.ads.googleads.v15.resources.types import google_ads_field +from google.ads.googleads.v15.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.v15.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.v15.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, + metadata: Sequence[Tuple[str, str]] = (), + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (:class:`google.ads.googleads.v15.services.types.SearchGoogleAdsFieldsRequest`): + The initial request object. + response (:class:`google.ads.googleads.v15.services.types.SearchGoogleAdsFieldsResponse`): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = google_ads_field_service.SearchGoogleAdsFieldsRequest( + request + ) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages( + self, + ) -> Iterable[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, 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) diff --git a/google/ads/googleads/v15/services/services/google_ads_field_service/transports/__init__.py b/google/ads/googleads/v15/services/services/google_ads_field_service/transports/__init__.py new file mode 100644 index 000000000..7a7342f96 --- /dev/null +++ b/google/ads/googleads/v15/services/services/google_ads_field_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[GoogleAdsFieldServiceTransport]] +_transport_registry["grpc"] = GoogleAdsFieldServiceGrpcTransport + +__all__ = ( + "GoogleAdsFieldServiceTransport", + "GoogleAdsFieldServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/google_ads_field_service/transports/base.py b/google/ads/googleads/v15/services/services/google_ads_field_service/transports/base.py new file mode 100644 index 000000000..1af29c6ee --- /dev/null +++ b/google/ads/googleads/v15/services/services/google_ads_field_service/transports/base.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.resources.types import google_ads_field +from google.ads.googleads.v15.services.types import google_ads_field_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("GoogleAdsFieldServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/google_ads_field_service/transports/grpc.py b/google/ads/googleads/v15/services/services/google_ads_field_service/transports/grpc.py new file mode 100644 index 000000000..5ee9aaa49 --- /dev/null +++ b/google/ads/googleads/v15/services/services/google_ads_field_service/transports/grpc.py @@ -0,0 +1,314 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.resources.types import google_ads_field +from google.ads.googleads.v15.services.types import google_ads_field_service +from .base import GoogleAdsFieldServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def get_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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("GoogleAdsFieldServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/google_ads_service/__init__.py b/google/ads/googleads/v15/services/services/google_ads_service/__init__.py new file mode 100644 index 000000000..a75af97f9 --- /dev/null +++ b/google/ads/googleads/v15/services/services/google_ads_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("GoogleAdsServiceClient",) diff --git a/google/ads/googleads/v15/services/services/google_ads_service/client.py b/google/ads/googleads/v15/services/services/google_ads_service/client.py new file mode 100644 index 000000000..54a530b73 --- /dev/null +++ b/google/ads/googleads/v15/services/services/google_ads_service/client.py @@ -0,0 +1,4474 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + Iterable, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.services.google_ads_service import pagers +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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_extension_setting_path( + customer_id: str, + ad_group_id: str, + extension_type: str, + ) -> str: + """Returns a fully-qualified ad_group_extension_setting string.""" + return "customers/{customer_id}/adGroupExtensionSettings/{ad_group_id}~{extension_type}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + extension_type=extension_type, + ) + + @staticmethod + def parse_ad_group_extension_setting_path(path: str) -> Dict[str, str]: + """Parses a ad_group_extension_setting path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupExtensionSettings/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def ad_group_feed_path( + customer_id: str, + ad_group_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified ad_group_feed string.""" + return "customers/{customer_id}/adGroupFeeds/{ad_group_id}~{feed_id}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_ad_group_feed_path(path: str) -> Dict[str, str]: + """Parses a ad_group_feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/adGroupFeeds/(?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 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 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_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_extension_setting_path( + customer_id: str, + campaign_id: str, + extension_type: str, + ) -> str: + """Returns a fully-qualified campaign_extension_setting string.""" + return "customers/{customer_id}/campaignExtensionSettings/{campaign_id}~{extension_type}".format( + customer_id=customer_id, + campaign_id=campaign_id, + extension_type=extension_type, + ) + + @staticmethod + def parse_campaign_extension_setting_path(path: str) -> Dict[str, str]: + """Parses a campaign_extension_setting path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignExtensionSettings/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def campaign_feed_path( + customer_id: str, + campaign_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified campaign_feed string.""" + return "customers/{customer_id}/campaignFeeds/{campaign_id}~{feed_id}".format( + customer_id=customer_id, + campaign_id=campaign_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_campaign_feed_path(path: str) -> Dict[str, str]: + """Parses a campaign_feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/campaignFeeds/(?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_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 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 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 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_extension_setting_path( + customer_id: str, + extension_type: str, + ) -> str: + """Returns a fully-qualified customer_extension_setting string.""" + return "customers/{customer_id}/customerExtensionSettings/{extension_type}".format( + customer_id=customer_id, + extension_type=extension_type, + ) + + @staticmethod + def parse_customer_extension_setting_path(path: str) -> Dict[str, str]: + """Parses a customer_extension_setting path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerExtensionSettings/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def customer_feed_path( + customer_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified customer_feed string.""" + return "customers/{customer_id}/customerFeeds/{feed_id}".format( + customer_id=customer_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_customer_feed_path(path: str) -> Dict[str, str]: + """Parses a customer_feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/customerFeeds/(?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 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 extension_feed_item_path( + customer_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified extension_feed_item string.""" + return ( + "customers/{customer_id}/extensionFeedItems/{feed_item_id}".format( + customer_id=customer_id, + feed_item_id=feed_item_id, + ) + ) + + @staticmethod + def parse_extension_feed_item_path(path: str) -> Dict[str, str]: + """Parses a extension_feed_item path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/extensionFeedItems/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_path( + customer_id: str, + feed_id: str, + ) -> str: + """Returns a fully-qualified feed string.""" + return "customers/{customer_id}/feeds/{feed_id}".format( + customer_id=customer_id, + feed_id=feed_id, + ) + + @staticmethod + def parse_feed_path(path: str) -> Dict[str, str]: + """Parses a feed path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feeds/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_item_path( + customer_id: str, + feed_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified feed_item string.""" + return ( + "customers/{customer_id}/feedItems/{feed_id}~{feed_item_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_id=feed_item_id, + ) + ) + + @staticmethod + def parse_feed_item_path(path: str) -> Dict[str, str]: + """Parses a feed_item path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItems/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_item_set_path( + customer_id: str, + feed_id: str, + feed_item_set_id: str, + ) -> str: + """Returns a fully-qualified feed_item_set string.""" + return "customers/{customer_id}/feedItemSets/{feed_id}~{feed_item_set_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_set_id=feed_item_set_id, + ) + + @staticmethod + def parse_feed_item_set_path(path: str) -> Dict[str, str]: + """Parses a feed_item_set path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItemSets/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_item_set_link_path( + customer_id: str, + feed_id: str, + feed_item_set_id: str, + feed_item_id: str, + ) -> str: + """Returns a fully-qualified feed_item_set_link string.""" + return "customers/{customer_id}/feedItemSetLinks/{feed_id}~{feed_item_set_id}~{feed_item_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_set_id=feed_item_set_id, + feed_item_id=feed_item_id, + ) + + @staticmethod + def parse_feed_item_set_link_path(path: str) -> Dict[str, str]: + """Parses a feed_item_set_link path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItemSetLinks/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_item_target_path( + customer_id: str, + feed_id: str, + feed_item_id: str, + feed_item_target_type: str, + feed_item_target_id: str, + ) -> str: + """Returns a fully-qualified feed_item_target string.""" + return "customers/{customer_id}/feedItemTargets/{feed_id}~{feed_item_id}~{feed_item_target_type}~{feed_item_target_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_item_id=feed_item_id, + feed_item_target_type=feed_item_target_type, + feed_item_target_id=feed_item_target_id, + ) + + @staticmethod + def parse_feed_item_target_path(path: str) -> Dict[str, str]: + """Parses a feed_item_target path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedItemTargets/(?P.+?)~(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_mapping_path( + customer_id: str, + feed_id: str, + feed_mapping_id: str, + ) -> str: + """Returns a fully-qualified feed_mapping string.""" + return "customers/{customer_id}/feedMappings/{feed_id}~{feed_mapping_id}".format( + customer_id=customer_id, + feed_id=feed_id, + feed_mapping_id=feed_mapping_id, + ) + + @staticmethod + def parse_feed_mapping_path(path: str) -> Dict[str, str]: + """Parses a feed_mapping path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedMappings/(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def feed_placeholder_view_path( + customer_id: str, + placeholder_type: str, + ) -> str: + """Returns a fully-qualified feed_placeholder_view string.""" + return "customers/{customer_id}/feedPlaceholderViews/{placeholder_type}".format( + customer_id=customer_id, + placeholder_type=placeholder_type, + ) + + @staticmethod + def parse_feed_placeholder_view_path(path: str) -> Dict[str, str]: + """Parses a feed_placeholder_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/feedPlaceholderViews/(?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 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_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_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 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_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 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 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 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_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 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 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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, GoogleAdsServiceTransport): + # transport is a GoogleAdsServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.SearchGoogleAdsRequest, dict, None]): + The request object. Request message for + [GoogleAdsService.Search][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.services.google_ads_service.pagers.SearchPager: + Response message for + [GoogleAdsService.Search][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, query]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a google_ads_service.SearchGoogleAdsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, + 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, str]] = (), + ) -> 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.v15.services.types.SearchGoogleAdsStreamRequest, dict, None]): + The request object. Request message for + [GoogleAdsService.SearchStream][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + Iterable[google.ads.googleads.v15.services.types.SearchGoogleAdsStreamResponse]: + Response message for + [GoogleAdsService.SearchStream][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, query]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a google_ads_service.SearchGoogleAdsStreamRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> google_ads_service.MutateGoogleAdsResponse: + r"""Creates, updates, or removes resources. This method supports + atomic transactions with multiple types of resources. 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.v15.services.types.MutateGoogleAdsRequest, dict, None]): + The request object. Request message for + [GoogleAdsService.Mutate][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateGoogleAdsResponse: + Response message for + [GoogleAdsService.Mutate][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, mutate_operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a google_ads_service.MutateGoogleAdsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("GoogleAdsServiceClient",) diff --git a/google/ads/googleads/v15/services/services/google_ads_service/pagers.py b/google/ads/googleads/v15/services/services/google_ads_service/pagers.py new file mode 100644 index 000000000..2ae4f29dd --- /dev/null +++ b/google/ads/googleads/v15/services/services/google_ads_service/pagers.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Any, Callable, Iterable, Iterator, Sequence, Tuple + +from google.ads.googleads.v15.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.v15.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.v15.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, + metadata: Sequence[Tuple[str, str]] = (), + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (:class:`google.ads.googleads.v15.services.types.SearchGoogleAdsRequest`): + The initial request object. + response (:class:`google.ads.googleads.v15.services.types.SearchGoogleAdsResponse`): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = google_ads_service.SearchGoogleAdsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages(self) -> Iterable[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, 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) diff --git a/google/ads/googleads/v15/services/services/google_ads_service/transports/__init__.py b/google/ads/googleads/v15/services/services/google_ads_service/transports/__init__.py new file mode 100644 index 000000000..b2091c6a8 --- /dev/null +++ b/google/ads/googleads/v15/services/services/google_ads_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[GoogleAdsServiceTransport]] +_transport_registry["grpc"] = GoogleAdsServiceGrpcTransport + +__all__ = ( + "GoogleAdsServiceTransport", + "GoogleAdsServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/google_ads_service/transports/base.py b/google/ads/googleads/v15/services/services/google_ads_service/transports/base.py new file mode 100644 index 000000000..1b0c14389 --- /dev/null +++ b/google/ads/googleads/v15/services/services/google_ads_service/transports/base.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import google_ads_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("GoogleAdsServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/google_ads_service/transports/grpc.py b/google/ads/googleads/v15/services/services/google_ads_service/transports/grpc.py new file mode 100644 index 000000000..8675f0d39 --- /dev/null +++ b/google/ads/googleads/v15/services/services/google_ads_service/transports/grpc.py @@ -0,0 +1,429 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import google_ads_service +from .base import GoogleAdsServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_stream( + "/google.ads.googleads.v15.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. + + Creates, updates, or removes resources. This method supports + atomic transactions with multiple types of resources. 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("GoogleAdsServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/invoice_service/__init__.py b/google/ads/googleads/v15/services/services/invoice_service/__init__.py new file mode 100644 index 000000000..954837c5f --- /dev/null +++ b/google/ads/googleads/v15/services/services/invoice_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("InvoiceServiceClient",) diff --git a/google/ads/googleads/v15/services/services/invoice_service/client.py b/google/ads/googleads/v15/services/services/invoice_service/client.py new file mode 100644 index 000000000..720817c87 --- /dev/null +++ b/google/ads/googleads/v15/services/services/invoice_service/client.py @@ -0,0 +1,542 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.enums.types import month_of_year +from google.ads.googleads.v15.services.types import invoice_service +from .transports.base import InvoiceServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import InvoiceServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, InvoiceServiceTransport): + # transport is a InvoiceServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.ListInvoicesRequest, dict, None]): + 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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.ListInvoicesResponse: + Response message for + [InvoiceService.ListInvoices][google.ads.googleads.v15.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. + has_flattened_params = any( + [customer_id, billing_setup, issue_year, issue_month] + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a invoice_service.ListInvoicesRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("InvoiceServiceClient",) diff --git a/google/ads/googleads/v15/services/services/invoice_service/transports/__init__.py b/google/ads/googleads/v15/services/services/invoice_service/transports/__init__.py new file mode 100644 index 000000000..58f31836e --- /dev/null +++ b/google/ads/googleads/v15/services/services/invoice_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[InvoiceServiceTransport]] +_transport_registry["grpc"] = InvoiceServiceGrpcTransport + +__all__ = ( + "InvoiceServiceTransport", + "InvoiceServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/invoice_service/transports/base.py b/google/ads/googleads/v15/services/services/invoice_service/transports/base.py new file mode 100644 index 000000000..88a6d2fb0 --- /dev/null +++ b/google/ads/googleads/v15/services/services/invoice_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import invoice_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("InvoiceServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/invoice_service/transports/grpc.py b/google/ads/googleads/v15/services/services/invoice_service/transports/grpc.py new file mode 100644 index 000000000..acd72706b --- /dev/null +++ b/google/ads/googleads/v15/services/services/invoice_service/transports/grpc.py @@ -0,0 +1,280 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import invoice_service +from .base import InvoiceServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.InvoiceService/ListInvoices", + request_serializer=invoice_service.ListInvoicesRequest.serialize, + response_deserializer=invoice_service.ListInvoicesResponse.deserialize, + ) + return self._stubs["list_invoices"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("InvoiceServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/__init__.py b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/__init__.py new file mode 100644 index 000000000..32e34be9f --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("KeywordPlanAdGroupKeywordServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/client.py b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/client.py new file mode 100644 index 000000000..a31378861 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/client.py @@ -0,0 +1,576 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, KeywordPlanAdGroupKeywordServiceTransport): + # transport is a KeywordPlanAdGroupKeywordServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateKeywordPlanAdGroupKeywordsRequest, dict, None]): + The request object. Request message for + [KeywordPlanAdGroupKeywordService.MutateKeywordPlanAdGroupKeywords][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a keyword_plan_ad_group_keyword_service.MutateKeywordPlanAdGroupKeywordsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("KeywordPlanAdGroupKeywordServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/transports/__init__.py b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/transports/__init__.py new file mode 100644 index 000000000..158c9f4dd --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordPlanAdGroupKeywordServiceTransport]] +_transport_registry["grpc"] = KeywordPlanAdGroupKeywordServiceGrpcTransport + +__all__ = ( + "KeywordPlanAdGroupKeywordServiceTransport", + "KeywordPlanAdGroupKeywordServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/transports/base.py b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/transports/base.py new file mode 100644 index 000000000..d8b2cc22b --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + keyword_plan_ad_group_keyword_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("KeywordPlanAdGroupKeywordServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/transports/grpc.py b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/transports/grpc.py new file mode 100644 index 000000000..a0e8c2751 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_keyword_service/transports/grpc.py @@ -0,0 +1,296 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + keyword_plan_ad_group_keyword_service, +) +from .base import KeywordPlanAdGroupKeywordServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("KeywordPlanAdGroupKeywordServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/__init__.py b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/__init__.py new file mode 100644 index 000000000..1c0078472 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("KeywordPlanAdGroupServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/client.py b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/client.py new file mode 100644 index 000000000..864f1df13 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/client.py @@ -0,0 +1,572 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, KeywordPlanAdGroupServiceTransport): + # transport is a KeywordPlanAdGroupServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateKeywordPlanAdGroupsRequest, dict, None]): + The request object. Request message for + [KeywordPlanAdGroupService.MutateKeywordPlanAdGroups][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a keyword_plan_ad_group_service.MutateKeywordPlanAdGroupsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("KeywordPlanAdGroupServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/transports/__init__.py b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/transports/__init__.py new file mode 100644 index 000000000..13816b5e2 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordPlanAdGroupServiceTransport]] +_transport_registry["grpc"] = KeywordPlanAdGroupServiceGrpcTransport + +__all__ = ( + "KeywordPlanAdGroupServiceTransport", + "KeywordPlanAdGroupServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/transports/base.py b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/transports/base.py new file mode 100644 index 000000000..4bf3461c5 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + keyword_plan_ad_group_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("KeywordPlanAdGroupServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/transports/grpc.py b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/transports/grpc.py new file mode 100644 index 000000000..3fb021eab --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_ad_group_service/transports/grpc.py @@ -0,0 +1,288 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + keyword_plan_ad_group_service, +) +from .base import KeywordPlanAdGroupServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("KeywordPlanAdGroupServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/__init__.py b/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/__init__.py new file mode 100644 index 000000000..67dbf14e0 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("KeywordPlanCampaignKeywordServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/client.py b/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/client.py new file mode 100644 index 000000000..d0c8f38a6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/client.py @@ -0,0 +1,574 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, KeywordPlanCampaignKeywordServiceTransport): + # transport is a KeywordPlanCampaignKeywordServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateKeywordPlanCampaignKeywordsRequest, dict, None]): + The request object. Request message for + [KeywordPlanCampaignKeywordService.MutateKeywordPlanCampaignKeywords][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a keyword_plan_campaign_keyword_service.MutateKeywordPlanCampaignKeywordsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("KeywordPlanCampaignKeywordServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/transports/__init__.py b/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/transports/__init__.py new file mode 100644 index 000000000..be82d5f2b --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordPlanCampaignKeywordServiceTransport]] +_transport_registry["grpc"] = KeywordPlanCampaignKeywordServiceGrpcTransport + +__all__ = ( + "KeywordPlanCampaignKeywordServiceTransport", + "KeywordPlanCampaignKeywordServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/transports/base.py b/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/transports/base.py new file mode 100644 index 000000000..266291a40 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + keyword_plan_campaign_keyword_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("KeywordPlanCampaignKeywordServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/transports/grpc.py b/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/transports/grpc.py new file mode 100644 index 000000000..83ae6ace1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_campaign_keyword_service/transports/grpc.py @@ -0,0 +1,297 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + keyword_plan_campaign_keyword_service, +) +from .base import ( + KeywordPlanCampaignKeywordServiceTransport, + DEFAULT_CLIENT_INFO, +) + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("KeywordPlanCampaignKeywordServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/__init__.py b/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/__init__.py new file mode 100644 index 000000000..c41bdd42f --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("KeywordPlanCampaignServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/client.py b/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/client.py new file mode 100644 index 000000000..ab5b6776d --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/client.py @@ -0,0 +1,602 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, KeywordPlanCampaignServiceTransport): + # transport is a KeywordPlanCampaignServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateKeywordPlanCampaignsRequest, dict, None]): + The request object. Request message for + [KeywordPlanCampaignService.MutateKeywordPlanCampaigns][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a keyword_plan_campaign_service.MutateKeywordPlanCampaignsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("KeywordPlanCampaignServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/transports/__init__.py b/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/transports/__init__.py new file mode 100644 index 000000000..e429b4f7b --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordPlanCampaignServiceTransport]] +_transport_registry["grpc"] = KeywordPlanCampaignServiceGrpcTransport + +__all__ = ( + "KeywordPlanCampaignServiceTransport", + "KeywordPlanCampaignServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/transports/base.py b/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/transports/base.py new file mode 100644 index 000000000..aa6a57437 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + keyword_plan_campaign_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("KeywordPlanCampaignServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/transports/grpc.py b/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/transports/grpc.py new file mode 100644 index 000000000..c85a6de2c --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_campaign_service/transports/grpc.py @@ -0,0 +1,288 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + keyword_plan_campaign_service, +) +from .base import KeywordPlanCampaignServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("KeywordPlanCampaignServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_idea_service/__init__.py b/google/ads/googleads/v15/services/services/keyword_plan_idea_service/__init__.py new file mode 100644 index 000000000..afcc4f808 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_idea_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("KeywordPlanIdeaServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_idea_service/client.py b/google/ads/googleads/v15/services/services/keyword_plan_idea_service/client.py new file mode 100644 index 000000000..bab4462d8 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_idea_service/client.py @@ -0,0 +1,707 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.services.keyword_plan_idea_service import ( + pagers, +) +from google.ads.googleads.v15.services.types import keyword_plan_idea_service +from .transports.base import ( + KeywordPlanIdeaServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import KeywordPlanIdeaServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, KeywordPlanIdeaServiceTransport): + # transport is a KeywordPlanIdeaServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.GenerateKeywordIdeasRequest, dict, None]): + The request object. Request message for + [KeywordPlanIdeaService.GenerateKeywordIdeas][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.services.keyword_plan_idea_service.pagers.GenerateKeywordIdeasPager: + Response message for + [KeywordPlanIdeaService.GenerateKeywordIdeas][google.ads.googleads.v15.services.KeywordPlanIdeaService.GenerateKeywordIdeas]. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a keyword_plan_idea_service.GenerateKeywordIdeasRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, + 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, str]] = (), + ) -> 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.v15.services.types.GenerateKeywordHistoricalMetricsRequest, dict, None]): + The request object. Request message for + [KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.GenerateKeywordHistoricalMetricsResponse: + Response message for + [KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics][google.ads.googleads.v15.services.KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics]. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a keyword_plan_idea_service.GenerateKeywordHistoricalMetricsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> 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.v15.services.types.GenerateAdGroupThemesRequest, dict, None]): + The request object. Request message for + [KeywordPlanIdeaService.GenerateAdGroupThemes][google.ads.googleads.v15.services.KeywordPlanIdeaService.GenerateAdGroupThemes]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.GenerateAdGroupThemesResponse: + Response message for + [KeywordPlanIdeaService.GenerateAdGroupThemes][google.ads.googleads.v15.services.KeywordPlanIdeaService.GenerateAdGroupThemes]. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a keyword_plan_idea_service.GenerateAdGroupThemesRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, keyword_plan_idea_service.GenerateAdGroupThemesRequest + ): + request = keyword_plan_idea_service.GenerateAdGroupThemesRequest( + request + ) + + # 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),) + ), + ) + + # 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, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> 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.v15.services.types.GenerateKeywordForecastMetricsRequest, dict, None]): + The request object. Request message for + [KeywordPlanIdeaService.GenerateKeywordForecastMetrics]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.GenerateKeywordForecastMetricsResponse: + Response message for + [KeywordPlanIdeaService.GenerateKeywordForecastMetrics]. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, + keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest, + ): + request = ( + keyword_plan_idea_service.GenerateKeywordForecastMetricsRequest( + request + ) + ) + + # 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("KeywordPlanIdeaServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_idea_service/pagers.py b/google/ads/googleads/v15/services/services/keyword_plan_idea_service/pagers.py new file mode 100644 index 000000000..318e1dab5 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_idea_service/pagers.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Any, Callable, Iterable, Iterator, Sequence, Tuple + +from google.ads.googleads.v15.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.v15.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.v15.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, + metadata: Sequence[Tuple[str, str]] = (), + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (:class:`google.ads.googleads.v15.services.types.GenerateKeywordIdeasRequest`): + The initial request object. + response (:class:`google.ads.googleads.v15.services.types.GenerateKeywordIdeaResponse`): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = keyword_plan_idea_service.GenerateKeywordIdeasRequest( + request + ) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages( + self, + ) -> Iterable[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, 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) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_idea_service/transports/__init__.py b/google/ads/googleads/v15/services/services/keyword_plan_idea_service/transports/__init__.py new file mode 100644 index 000000000..b0546bd0b --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_idea_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordPlanIdeaServiceTransport]] +_transport_registry["grpc"] = KeywordPlanIdeaServiceGrpcTransport + +__all__ = ( + "KeywordPlanIdeaServiceTransport", + "KeywordPlanIdeaServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_idea_service/transports/base.py b/google/ads/googleads/v15/services/services/keyword_plan_idea_service/transports/base.py new file mode 100644 index 000000000..e811c9385 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_idea_service/transports/base.py @@ -0,0 +1,211 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import keyword_plan_idea_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("KeywordPlanIdeaServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_idea_service/transports/grpc.py b/google/ads/googleads/v15/services/services/keyword_plan_idea_service/transports/grpc.py new file mode 100644 index 000000000..06651875c --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_idea_service/transports/grpc.py @@ -0,0 +1,393 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import keyword_plan_idea_service +from .base import KeywordPlanIdeaServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("KeywordPlanIdeaServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_service/__init__.py b/google/ads/googleads/v15/services/services/keyword_plan_service/__init__.py new file mode 100644 index 000000000..3349792a1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("KeywordPlanServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_service/client.py b/google/ads/googleads/v15/services/services/keyword_plan_service/client.py new file mode 100644 index 000000000..00ce75810 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_service/client.py @@ -0,0 +1,530 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, KeywordPlanServiceTransport): + # transport is a KeywordPlanServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateKeywordPlansRequest, dict, None]): + The request object. Request message for + [KeywordPlanService.MutateKeywordPlans][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a keyword_plan_service.MutateKeywordPlansRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("KeywordPlanServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_service/transports/__init__.py b/google/ads/googleads/v15/services/services/keyword_plan_service/transports/__init__.py new file mode 100644 index 000000000..600029131 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordPlanServiceTransport]] +_transport_registry["grpc"] = KeywordPlanServiceGrpcTransport + +__all__ = ( + "KeywordPlanServiceTransport", + "KeywordPlanServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_service/transports/base.py b/google/ads/googleads/v15/services/services/keyword_plan_service/transports/base.py new file mode 100644 index 000000000..f54aad131 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import keyword_plan_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("KeywordPlanServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_plan_service/transports/grpc.py b/google/ads/googleads/v15/services/services/keyword_plan_service/transports/grpc.py new file mode 100644 index 000000000..673253250 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_plan_service/transports/grpc.py @@ -0,0 +1,281 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import keyword_plan_service +from .base import KeywordPlanServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("KeywordPlanServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_theme_constant_service/__init__.py b/google/ads/googleads/v15/services/services/keyword_theme_constant_service/__init__.py new file mode 100644 index 000000000..64b383282 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_theme_constant_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("KeywordThemeConstantServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_theme_constant_service/client.py b/google/ads/googleads/v15/services/services/keyword_theme_constant_service/client.py new file mode 100644 index 000000000..f71f4c901 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_theme_constant_service/client.py @@ -0,0 +1,490 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + keyword_theme_constant_service, +) +from .transports.base import ( + KeywordThemeConstantServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import KeywordThemeConstantServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, KeywordThemeConstantServiceTransport): + # transport is a KeywordThemeConstantServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.SuggestKeywordThemeConstantsRequest, dict, None]): + The request object. Request message for + [KeywordThemeConstantService.SuggestKeywordThemeConstants][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.SuggestKeywordThemeConstantsResponse: + Response message for + [KeywordThemeConstantService.SuggestKeywordThemeConstants][google.ads.googleads.v15.services.KeywordThemeConstantService.SuggestKeywordThemeConstants]. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a keyword_theme_constant_service.SuggestKeywordThemeConstantsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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 + ] + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("KeywordThemeConstantServiceClient",) diff --git a/google/ads/googleads/v15/services/services/keyword_theme_constant_service/transports/__init__.py b/google/ads/googleads/v15/services/services/keyword_theme_constant_service/transports/__init__.py new file mode 100644 index 000000000..2bdb72da2 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_theme_constant_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[KeywordThemeConstantServiceTransport]] +_transport_registry["grpc"] = KeywordThemeConstantServiceGrpcTransport + +__all__ = ( + "KeywordThemeConstantServiceTransport", + "KeywordThemeConstantServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/keyword_theme_constant_service/transports/base.py b/google/ads/googleads/v15/services/services/keyword_theme_constant_service/transports/base.py new file mode 100644 index 000000000..b8c824eb1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_theme_constant_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + keyword_theme_constant_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("KeywordThemeConstantServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/keyword_theme_constant_service/transports/grpc.py b/google/ads/googleads/v15/services/services/keyword_theme_constant_service/transports/grpc.py new file mode 100644 index 000000000..023f22c2f --- /dev/null +++ b/google/ads/googleads/v15/services/services/keyword_theme_constant_service/transports/grpc.py @@ -0,0 +1,284 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + keyword_theme_constant_service, +) +from .base import KeywordThemeConstantServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("KeywordThemeConstantServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/label_service/__init__.py b/google/ads/googleads/v15/services/services/label_service/__init__.py new file mode 100644 index 000000000..ca923d763 --- /dev/null +++ b/google/ads/googleads/v15/services/services/label_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("LabelServiceClient",) diff --git a/google/ads/googleads/v15/services/services/label_service/client.py b/google/ads/googleads/v15/services/services/label_service/client.py new file mode 100644 index 000000000..a5d1a2da2 --- /dev/null +++ b/google/ads/googleads/v15/services/services/label_service/client.py @@ -0,0 +1,527 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, LabelServiceTransport): + # transport is a LabelServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateLabelsRequest, dict, None]): + The request object. Request message for + [LabelService.MutateLabels][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a label_service.MutateLabelsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("LabelServiceClient",) diff --git a/google/ads/googleads/v15/services/services/label_service/transports/__init__.py b/google/ads/googleads/v15/services/services/label_service/transports/__init__.py new file mode 100644 index 000000000..fd3c07e22 --- /dev/null +++ b/google/ads/googleads/v15/services/services/label_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[LabelServiceTransport]] +_transport_registry["grpc"] = LabelServiceGrpcTransport + +__all__ = ( + "LabelServiceTransport", + "LabelServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/label_service/transports/base.py b/google/ads/googleads/v15/services/services/label_service/transports/base.py new file mode 100644 index 000000000..553d3d577 --- /dev/null +++ b/google/ads/googleads/v15/services/services/label_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import label_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("LabelServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/label_service/transports/grpc.py b/google/ads/googleads/v15/services/services/label_service/transports/grpc.py new file mode 100644 index 000000000..95e9e1153 --- /dev/null +++ b/google/ads/googleads/v15/services/services/label_service/transports/grpc.py @@ -0,0 +1,284 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import label_service +from .base import LabelServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.LabelService/MutateLabels", + request_serializer=label_service.MutateLabelsRequest.serialize, + response_deserializer=label_service.MutateLabelsResponse.deserialize, + ) + return self._stubs["mutate_labels"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("LabelServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/offline_user_data_job_service/__init__.py b/google/ads/googleads/v15/services/services/offline_user_data_job_service/__init__.py new file mode 100644 index 000000000..13c5c5ba1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/offline_user_data_job_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("OfflineUserDataJobServiceClient",) diff --git a/google/ads/googleads/v15/services/services/offline_user_data_job_service/client.py b/google/ads/googleads/v15/services/services/offline_user_data_job_service/client.py new file mode 100644 index 000000000..3eb814260 --- /dev/null +++ b/google/ads/googleads/v15/services/services/offline_user_data_job_service/client.py @@ -0,0 +1,775 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.resources.types import offline_user_data_job +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, OfflineUserDataJobServiceTransport): + # transport is a OfflineUserDataJobServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.CreateOfflineUserDataJobRequest, dict, None]): + The request object. Request message for + [OfflineUserDataJobService.CreateOfflineUserDataJob][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.CreateOfflineUserDataJobResponse: + Response message for + [OfflineUserDataJobService.CreateOfflineUserDataJob][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, job]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a offline_user_data_job_service.CreateOfflineUserDataJobRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.AddOfflineUserDataJobOperationsRequest, dict, None]): + The request object. Request message for + [OfflineUserDataJobService.AddOfflineUserDataJobOperations][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.AddOfflineUserDataJobOperationsResponse: + Response message for + [OfflineUserDataJobService.AddOfflineUserDataJobOperations][google.ads.googleads.v15.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. + has_flattened_params = any([resource_name, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a offline_user_data_job_service.AddOfflineUserDataJobOperationsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.RunOfflineUserDataJobRequest, dict, None]): + The request object. Request message for + [OfflineUserDataJobService.RunOfflineUserDataJob][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.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. + has_flattened_params = any([resource_name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a offline_user_data_job_service.RunOfflineUserDataJobRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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 + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("OfflineUserDataJobServiceClient",) diff --git a/google/ads/googleads/v15/services/services/offline_user_data_job_service/transports/__init__.py b/google/ads/googleads/v15/services/services/offline_user_data_job_service/transports/__init__.py new file mode 100644 index 000000000..b74936992 --- /dev/null +++ b/google/ads/googleads/v15/services/services/offline_user_data_job_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[OfflineUserDataJobServiceTransport]] +_transport_registry["grpc"] = OfflineUserDataJobServiceGrpcTransport + +__all__ = ( + "OfflineUserDataJobServiceTransport", + "OfflineUserDataJobServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/offline_user_data_job_service/transports/base.py b/google/ads/googleads/v15/services/services/offline_user_data_job_service/transports/base.py new file mode 100644 index 000000000..ed8cf8587 --- /dev/null +++ b/google/ads/googleads/v15/services/services/offline_user_data_job_service/transports/base.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + offline_user_data_job_service, +) +from google.longrunning import operations_pb2 # type: ignore + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("OfflineUserDataJobServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/offline_user_data_job_service/transports/grpc.py b/google/ads/googleads/v15/services/services/offline_user_data_job_service/transports/grpc.py new file mode 100644 index 000000000..5a2c177a9 --- /dev/null +++ b/google/ads/googleads/v15/services/services/offline_user_data_job_service/transports/grpc.py @@ -0,0 +1,382 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + offline_user_data_job_service, +) +from google.longrunning import operations_pb2 # type: ignore +from .base import OfflineUserDataJobServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client: Optional[operations_v1.OperationsClient] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def operations_client(self) -> operations_v1.OperationsClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsClient( + self.grpc_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("OfflineUserDataJobServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/payments_account_service/__init__.py b/google/ads/googleads/v15/services/services/payments_account_service/__init__.py new file mode 100644 index 000000000..64a7da472 --- /dev/null +++ b/google/ads/googleads/v15/services/services/payments_account_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("PaymentsAccountServiceClient",) diff --git a/google/ads/googleads/v15/services/services/payments_account_service/client.py b/google/ads/googleads/v15/services/services/payments_account_service/client.py new file mode 100644 index 000000000..e7df5fdca --- /dev/null +++ b/google/ads/googleads/v15/services/services/payments_account_service/client.py @@ -0,0 +1,530 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import payments_account_service +from .transports.base import ( + PaymentsAccountServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import PaymentsAccountServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, PaymentsAccountServiceTransport): + # transport is a PaymentsAccountServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.ListPaymentsAccountsRequest, dict, None]): + 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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.ListPaymentsAccountsResponse: + Response message for + [PaymentsAccountService.ListPaymentsAccounts][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a payments_account_service.ListPaymentsAccountsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("PaymentsAccountServiceClient",) diff --git a/google/ads/googleads/v15/services/services/payments_account_service/transports/__init__.py b/google/ads/googleads/v15/services/services/payments_account_service/transports/__init__.py new file mode 100644 index 000000000..7106aafc6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/payments_account_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[PaymentsAccountServiceTransport]] +_transport_registry["grpc"] = PaymentsAccountServiceGrpcTransport + +__all__ = ( + "PaymentsAccountServiceTransport", + "PaymentsAccountServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/payments_account_service/transports/base.py b/google/ads/googleads/v15/services/services/payments_account_service/transports/base.py new file mode 100644 index 000000000..521d75871 --- /dev/null +++ b/google/ads/googleads/v15/services/services/payments_account_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import payments_account_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("PaymentsAccountServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/payments_account_service/transports/grpc.py b/google/ads/googleads/v15/services/services/payments_account_service/transports/grpc.py new file mode 100644 index 000000000..f29788281 --- /dev/null +++ b/google/ads/googleads/v15/services/services/payments_account_service/transports/grpc.py @@ -0,0 +1,283 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import payments_account_service +from .base import PaymentsAccountServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("PaymentsAccountServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/product_link_invitation_service/__init__.py b/google/ads/googleads/v15/services/services/product_link_invitation_service/__init__.py new file mode 100644 index 000000000..6afe968bc --- /dev/null +++ b/google/ads/googleads/v15/services/services/product_link_invitation_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("ProductLinkInvitationServiceClient",) diff --git a/google/ads/googleads/v15/services/services/product_link_invitation_service/client.py b/google/ads/googleads/v15/services/services/product_link_invitation_service/client.py new file mode 100644 index 000000000..1a0ab588f --- /dev/null +++ b/google/ads/googleads/v15/services/services/product_link_invitation_service/client.py @@ -0,0 +1,546 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.enums.types import ( + product_link_invitation_status as gage_product_link_invitation_status, +) +from google.ads.googleads.v15.services.types import ( + product_link_invitation_service, +) +from .transports.base import ( + ProductLinkInvitationServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ProductLinkInvitationServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ProductLinkInvitationServiceTransport): + # transport is a ProductLinkInvitationServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> product_link_invitation_service.UpdateProductLinkInvitationResponse: + r"""Update a product link invitation. + + Args: + request (Union[google.ads.googleads.v15.services.types.UpdateProductLinkInvitationRequest, dict, None]): + The request object. Request message for + [ProductLinkInvitationService.UpdateProductLinkInvitation][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any( + [customer_id, product_link_invitation_status, resource_name] + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a product_link_invitation_service.UpdateProductLinkInvitationRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ProductLinkInvitationServiceClient",) diff --git a/google/ads/googleads/v15/services/services/product_link_invitation_service/transports/__init__.py b/google/ads/googleads/v15/services/services/product_link_invitation_service/transports/__init__.py new file mode 100644 index 000000000..fdc795420 --- /dev/null +++ b/google/ads/googleads/v15/services/services/product_link_invitation_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ProductLinkInvitationServiceTransport]] +_transport_registry["grpc"] = ProductLinkInvitationServiceGrpcTransport + +__all__ = ( + "ProductLinkInvitationServiceTransport", + "ProductLinkInvitationServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/product_link_invitation_service/transports/base.py b/google/ads/googleads/v15/services/services/product_link_invitation_service/transports/base.py new file mode 100644 index 000000000..6016640ec --- /dev/null +++ b/google/ads/googleads/v15/services/services/product_link_invitation_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + product_link_invitation_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.update_product_link_invitation: gapic_v1.method.wrap_method( + self.update_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 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() + + +__all__ = ("ProductLinkInvitationServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/product_link_invitation_service/transports/grpc.py b/google/ads/googleads/v15/services/services/product_link_invitation_service/transports/grpc.py new file mode 100644 index 000000000..3801fd993 --- /dev/null +++ b/google/ads/googleads/v15/services/services/product_link_invitation_service/transports/grpc.py @@ -0,0 +1,280 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + product_link_invitation_service, +) +from .base import ProductLinkInvitationServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def update_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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("ProductLinkInvitationServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/product_link_service/__init__.py b/google/ads/googleads/v15/services/services/product_link_service/__init__.py new file mode 100644 index 000000000..ab3e5d2a1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/product_link_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("ProductLinkServiceClient",) diff --git a/google/ads/googleads/v15/services/services/product_link_service/client.py b/google/ads/googleads/v15/services/services/product_link_service/client.py new file mode 100644 index 000000000..c2040faa4 --- /dev/null +++ b/google/ads/googleads/v15/services/services/product_link_service/client.py @@ -0,0 +1,636 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.resources.types import ( + product_link as gagr_product_link, +) +from google.ads.googleads.v15.services.types import product_link_service +from .transports.base import ProductLinkServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import ProductLinkServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ProductLinkServiceTransport): + # transport is a ProductLinkServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.CreateProductLinkRequest, dict, None]): + The request object. Request message for + [ProductLinkService.CreateProductLink][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.CreateProductLinkResponse: + Response message for + [ProductLinkService.CreateProductLink][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, product_link]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a product_link_service.CreateProductLinkRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> 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.v15.services.types.RemoveProductLinkRequest, dict, None]): + The request object. Request message for + [ProductLinkService.RemoveProductLink][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, resource_name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a product_link_service.RemoveProductLinkRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ProductLinkServiceClient",) diff --git a/google/ads/googleads/v15/services/services/product_link_service/transports/__init__.py b/google/ads/googleads/v15/services/services/product_link_service/transports/__init__.py new file mode 100644 index 000000000..1114cc886 --- /dev/null +++ b/google/ads/googleads/v15/services/services/product_link_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ProductLinkServiceTransport]] +_transport_registry["grpc"] = ProductLinkServiceGrpcTransport + +__all__ = ( + "ProductLinkServiceTransport", + "ProductLinkServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/product_link_service/transports/base.py b/google/ads/googleads/v15/services/services/product_link_service/transports/base.py new file mode 100644 index 000000000..9fbdf4cee --- /dev/null +++ b/google/ads/googleads/v15/services/services/product_link_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import product_link_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("ProductLinkServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/product_link_service/transports/grpc.py b/google/ads/googleads/v15/services/services/product_link_service/transports/grpc.py new file mode 100644 index 000000000..819c4aaae --- /dev/null +++ b/google/ads/googleads/v15/services/services/product_link_service/transports/grpc.py @@ -0,0 +1,313 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import product_link_service +from .base import ProductLinkServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("ProductLinkServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/reach_plan_service/__init__.py b/google/ads/googleads/v15/services/services/reach_plan_service/__init__.py new file mode 100644 index 000000000..408d07456 --- /dev/null +++ b/google/ads/googleads/v15/services/services/reach_plan_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("ReachPlanServiceClient",) diff --git a/google/ads/googleads/v15/services/services/reach_plan_service/client.py b/google/ads/googleads/v15/services/services/reach_plan_service/client.py new file mode 100644 index 000000000..2720c7ed7 --- /dev/null +++ b/google/ads/googleads/v15/services/services/reach_plan_service/client.py @@ -0,0 +1,661 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import reach_plan_service +from .transports.base import ReachPlanServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import ReachPlanServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ReachPlanServiceTransport): + # transport is a ReachPlanServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.ListPlannableLocationsRequest, dict, None]): + The request object. Request message for + [ReachPlanService.ListPlannableLocations][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.ListPlannableLocationsResponse: + The list of plannable locations. + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a reach_plan_service.ListPlannableLocationsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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 + ] + + # 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, str]] = (), + ) -> 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.v15.services.types.ListPlannableProductsRequest, dict, None]): + 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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([plannable_location_id]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a reach_plan_service.ListPlannableProductsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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 + ] + + # 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, str]] = (), + ) -> 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.v15.services.types.GenerateReachForecastRequest, dict, None]): + The request object. Request message for + [ReachPlanService.GenerateReachForecast][google.ads.googleads.v15.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.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any( + [customer_id, campaign_duration, planned_products] + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a reach_plan_service.GenerateReachForecastRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ReachPlanServiceClient",) diff --git a/google/ads/googleads/v15/services/services/reach_plan_service/transports/__init__.py b/google/ads/googleads/v15/services/services/reach_plan_service/transports/__init__.py new file mode 100644 index 000000000..f8ef4031e --- /dev/null +++ b/google/ads/googleads/v15/services/services/reach_plan_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ReachPlanServiceTransport]] +_transport_registry["grpc"] = ReachPlanServiceGrpcTransport + +__all__ = ( + "ReachPlanServiceTransport", + "ReachPlanServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/reach_plan_service/transports/base.py b/google/ads/googleads/v15/services/services/reach_plan_service/transports/base.py new file mode 100644 index 000000000..8793cd706 --- /dev/null +++ b/google/ads/googleads/v15/services/services/reach_plan_service/transports/base.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import reach_plan_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + 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, + ), + } + + 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_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() + + +__all__ = ("ReachPlanServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/reach_plan_service/transports/grpc.py b/google/ads/googleads/v15/services/services/reach_plan_service/transports/grpc.py new file mode 100644 index 000000000..da6c34ede --- /dev/null +++ b/google/ads/googleads/v15/services/services/reach_plan_service/transports/grpc.py @@ -0,0 +1,357 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import reach_plan_service +from .base import ReachPlanServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.ReachPlanService/GenerateReachForecast", + request_serializer=reach_plan_service.GenerateReachForecastRequest.serialize, + response_deserializer=reach_plan_service.GenerateReachForecastResponse.deserialize, + ) + return self._stubs["generate_reach_forecast"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("ReachPlanServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/recommendation_service/__init__.py b/google/ads/googleads/v15/services/services/recommendation_service/__init__.py new file mode 100644 index 000000000..0ff05cf98 --- /dev/null +++ b/google/ads/googleads/v15/services/services/recommendation_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("RecommendationServiceClient",) diff --git a/google/ads/googleads/v15/services/services/recommendation_service/client.py b/google/ads/googleads/v15/services/services/recommendation_service/client.py new file mode 100644 index 000000000..41021e438 --- /dev/null +++ b/google/ads/googleads/v15/services/services/recommendation_service/client.py @@ -0,0 +1,696 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 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 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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, RecommendationServiceTransport]] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the recommendation service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str, RecommendationServiceTransport]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, RecommendationServiceTransport): + # transport is a RecommendationServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.ApplyRecommendationRequest, dict, None]): + The request object. Request message for + [RecommendationService.ApplyRecommendation][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.ApplyRecommendationResponse: + Response message for + [RecommendationService.ApplyRecommendation][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a recommendation_service.ApplyRecommendationRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> recommendation_service.DismissRecommendationResponse: + r"""Dismisses given recommendations. + + List of thrown errors: `AuthenticationError <>`__ + `AuthorizationError <>`__ `HeaderError <>`__ + `InternalError <>`__ `QuotaError <>`__ + `RecommendationError <>`__ `RequestError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.DismissRecommendationRequest, dict, None]): + The request object. Request message for + [RecommendationService.DismissRecommendation][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.DismissRecommendationResponse: + Response message for + [RecommendationService.DismissRecommendation][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a recommendation_service.DismissRecommendationRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("RecommendationServiceClient",) diff --git a/google/ads/googleads/v15/services/services/recommendation_service/transports/__init__.py b/google/ads/googleads/v15/services/services/recommendation_service/transports/__init__.py new file mode 100644 index 000000000..866c214cb --- /dev/null +++ b/google/ads/googleads/v15/services/services/recommendation_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[RecommendationServiceTransport]] +_transport_registry["grpc"] = RecommendationServiceGrpcTransport + +__all__ = ( + "RecommendationServiceTransport", + "RecommendationServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/recommendation_service/transports/base.py b/google/ads/googleads/v15/services/services/recommendation_service/transports/base.py new file mode 100644 index 000000000..830dd84cd --- /dev/null +++ b/google/ads/googleads/v15/services/services/recommendation_service/transports/base.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import recommendation_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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, + ), + } + + 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() + + +__all__ = ("RecommendationServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/recommendation_service/transports/grpc.py b/google/ads/googleads/v15/services/services/recommendation_service/transports/grpc.py new file mode 100644 index 000000000..5befa8ee1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/recommendation_service/transports/grpc.py @@ -0,0 +1,316 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import recommendation_service +from .base import RecommendationServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.services.RecommendationService/DismissRecommendation", + request_serializer=recommendation_service.DismissRecommendationRequest.serialize, + response_deserializer=recommendation_service.DismissRecommendationResponse.deserialize, + ) + return self._stubs["dismiss_recommendation"] + + def close(self): + self.grpc_channel.close() + + +__all__ = ("RecommendationServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/recommendation_subscription_service/__init__.py b/google/ads/googleads/v15/services/services/recommendation_subscription_service/__init__.py new file mode 100644 index 000000000..141398712 --- /dev/null +++ b/google/ads/googleads/v15/services/services/recommendation_subscription_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("RecommendationSubscriptionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/recommendation_subscription_service/client.py b/google/ads/googleads/v15/services/services/recommendation_subscription_service/client.py new file mode 100644 index 000000000..15f3aa964 --- /dev/null +++ b/google/ads/googleads/v15/services/services/recommendation_subscription_service/client.py @@ -0,0 +1,545 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, RecommendationSubscriptionServiceTransport): + # transport is a RecommendationSubscriptionServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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 <>`__ `RequestError <>`__ + `UrlFieldError <>`__ + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateRecommendationSubscriptionRequest, dict, None]): + The request object. Request message for + [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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.MutateRecommendationSubscriptionResponse: + Response message for + [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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a recommendation_subscription_service.MutateRecommendationSubscriptionRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("RecommendationSubscriptionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/recommendation_subscription_service/transports/__init__.py b/google/ads/googleads/v15/services/services/recommendation_subscription_service/transports/__init__.py new file mode 100644 index 000000000..bd20d95d1 --- /dev/null +++ b/google/ads/googleads/v15/services/services/recommendation_subscription_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[RecommendationSubscriptionServiceTransport]] +_transport_registry["grpc"] = RecommendationSubscriptionServiceGrpcTransport + +__all__ = ( + "RecommendationSubscriptionServiceTransport", + "RecommendationSubscriptionServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/recommendation_subscription_service/transports/base.py b/google/ads/googleads/v15/services/services/recommendation_subscription_service/transports/base.py new file mode 100644 index 000000000..255b80246 --- /dev/null +++ b/google/ads/googleads/v15/services/services/recommendation_subscription_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + recommendation_subscription_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("RecommendationSubscriptionServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/recommendation_subscription_service/transports/grpc.py b/google/ads/googleads/v15/services/services/recommendation_subscription_service/transports/grpc.py new file mode 100644 index 000000000..757a78083 --- /dev/null +++ b/google/ads/googleads/v15/services/services/recommendation_subscription_service/transports/grpc.py @@ -0,0 +1,291 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + recommendation_subscription_service, +) +from .base import ( + RecommendationSubscriptionServiceTransport, + DEFAULT_CLIENT_INFO, +) + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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 <>`__ `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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("RecommendationSubscriptionServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/remarketing_action_service/__init__.py b/google/ads/googleads/v15/services/services/remarketing_action_service/__init__.py new file mode 100644 index 000000000..20c75adf6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/remarketing_action_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("RemarketingActionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/remarketing_action_service/client.py b/google/ads/googleads/v15/services/services/remarketing_action_service/client.py new file mode 100644 index 000000000..9d217bb3f --- /dev/null +++ b/google/ads/googleads/v15/services/services/remarketing_action_service/client.py @@ -0,0 +1,545 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, RemarketingActionServiceTransport): + # transport is a RemarketingActionServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateRemarketingActionsRequest, dict, None]): + The request object. Request message for + [RemarketingActionService.MutateRemarketingActions][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a remarketing_action_service.MutateRemarketingActionsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("RemarketingActionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/remarketing_action_service/transports/__init__.py b/google/ads/googleads/v15/services/services/remarketing_action_service/transports/__init__.py new file mode 100644 index 000000000..cefc9e7ae --- /dev/null +++ b/google/ads/googleads/v15/services/services/remarketing_action_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[RemarketingActionServiceTransport]] +_transport_registry["grpc"] = RemarketingActionServiceGrpcTransport + +__all__ = ( + "RemarketingActionServiceTransport", + "RemarketingActionServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/remarketing_action_service/transports/base.py b/google/ads/googleads/v15/services/services/remarketing_action_service/transports/base.py new file mode 100644 index 000000000..353366360 --- /dev/null +++ b/google/ads/googleads/v15/services/services/remarketing_action_service/transports/base.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import remarketing_action_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("RemarketingActionServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/remarketing_action_service/transports/grpc.py b/google/ads/googleads/v15/services/services/remarketing_action_service/transports/grpc.py new file mode 100644 index 000000000..8b3b1e77d --- /dev/null +++ b/google/ads/googleads/v15/services/services/remarketing_action_service/transports/grpc.py @@ -0,0 +1,281 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import remarketing_action_service +from .base import RemarketingActionServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("RemarketingActionServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/shared_criterion_service/__init__.py b/google/ads/googleads/v15/services/services/shared_criterion_service/__init__.py new file mode 100644 index 000000000..4d3fee989 --- /dev/null +++ b/google/ads/googleads/v15/services/services/shared_criterion_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("SharedCriterionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/shared_criterion_service/client.py b/google/ads/googleads/v15/services/services/shared_criterion_service/client.py new file mode 100644 index 000000000..baffdedb2 --- /dev/null +++ b/google/ads/googleads/v15/services/services/shared_criterion_service/client.py @@ -0,0 +1,579 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, SharedCriterionServiceTransport): + # transport is a SharedCriterionServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateSharedCriteriaRequest, dict, None]): + The request object. Request message for + [SharedCriterionService.MutateSharedCriteria][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a shared_criterion_service.MutateSharedCriteriaRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("SharedCriterionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/shared_criterion_service/transports/__init__.py b/google/ads/googleads/v15/services/services/shared_criterion_service/transports/__init__.py new file mode 100644 index 000000000..b38514608 --- /dev/null +++ b/google/ads/googleads/v15/services/services/shared_criterion_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[SharedCriterionServiceTransport]] +_transport_registry["grpc"] = SharedCriterionServiceGrpcTransport + +__all__ = ( + "SharedCriterionServiceTransport", + "SharedCriterionServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/shared_criterion_service/transports/base.py b/google/ads/googleads/v15/services/services/shared_criterion_service/transports/base.py new file mode 100644 index 000000000..ef0d88689 --- /dev/null +++ b/google/ads/googleads/v15/services/services/shared_criterion_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import shared_criterion_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("SharedCriterionServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/shared_criterion_service/transports/grpc.py b/google/ads/googleads/v15/services/services/shared_criterion_service/transports/grpc.py new file mode 100644 index 000000000..7dfd63ada --- /dev/null +++ b/google/ads/googleads/v15/services/services/shared_criterion_service/transports/grpc.py @@ -0,0 +1,286 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import shared_criterion_service +from .base import SharedCriterionServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("SharedCriterionServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/shared_set_service/__init__.py b/google/ads/googleads/v15/services/services/shared_set_service/__init__.py new file mode 100644 index 000000000..f0657edcc --- /dev/null +++ b/google/ads/googleads/v15/services/services/shared_set_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("SharedSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/shared_set_service/client.py b/google/ads/googleads/v15/services/services/shared_set_service/client.py new file mode 100644 index 000000000..8302952d9 --- /dev/null +++ b/google/ads/googleads/v15/services/services/shared_set_service/client.py @@ -0,0 +1,532 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, SharedSetServiceTransport): + # transport is a SharedSetServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateSharedSetsRequest, dict, None]): + The request object. Request message for + [SharedSetService.MutateSharedSets][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a shared_set_service.MutateSharedSetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("SharedSetServiceClient",) diff --git a/google/ads/googleads/v15/services/services/shared_set_service/transports/__init__.py b/google/ads/googleads/v15/services/services/shared_set_service/transports/__init__.py new file mode 100644 index 000000000..a9db2811f --- /dev/null +++ b/google/ads/googleads/v15/services/services/shared_set_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[SharedSetServiceTransport]] +_transport_registry["grpc"] = SharedSetServiceGrpcTransport + +__all__ = ( + "SharedSetServiceTransport", + "SharedSetServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/shared_set_service/transports/base.py b/google/ads/googleads/v15/services/services/shared_set_service/transports/base.py new file mode 100644 index 000000000..0656d9388 --- /dev/null +++ b/google/ads/googleads/v15/services/services/shared_set_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import shared_set_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("SharedSetServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/shared_set_service/transports/grpc.py b/google/ads/googleads/v15/services/services/shared_set_service/transports/grpc.py new file mode 100644 index 000000000..505a17016 --- /dev/null +++ b/google/ads/googleads/v15/services/services/shared_set_service/transports/grpc.py @@ -0,0 +1,285 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import shared_set_service +from .base import SharedSetServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("SharedSetServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/smart_campaign_setting_service/__init__.py b/google/ads/googleads/v15/services/services/smart_campaign_setting_service/__init__.py new file mode 100644 index 000000000..2cb2d3411 --- /dev/null +++ b/google/ads/googleads/v15/services/services/smart_campaign_setting_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("SmartCampaignSettingServiceClient",) diff --git a/google/ads/googleads/v15/services/services/smart_campaign_setting_service/client.py b/google/ads/googleads/v15/services/services/smart_campaign_setting_service/client.py new file mode 100644 index 000000000..4b73a4db6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/smart_campaign_setting_service/client.py @@ -0,0 +1,652 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, SmartCampaignSettingServiceTransport): + # transport is a SmartCampaignSettingServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> smart_campaign_setting_service.GetSmartCampaignStatusResponse: + r"""Returns the status of the requested Smart campaign. + + Args: + request (Union[google.ads.googleads.v15.services.types.GetSmartCampaignStatusRequest, dict, None]): + The request object. Request message for + [SmartCampaignSettingService.GetSmartCampaignStatus][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.GetSmartCampaignStatusResponse: + Response message for + [SmartCampaignSettingService.GetSmartCampaignStatus][google.ads.googleads.v15.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. + has_flattened_params = any([resource_name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a smart_campaign_setting_service.GetSmartCampaignStatusRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, str]] = (), + ) -> smart_campaign_setting_service.MutateSmartCampaignSettingsResponse: + r"""Updates Smart campaign settings for campaigns. + + Args: + request (Union[google.ads.googleads.v15.services.types.MutateSmartCampaignSettingsRequest, dict, None]): + The request object. Request message for + [SmartCampaignSettingService.MutateSmartCampaignSettings][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a smart_campaign_setting_service.MutateSmartCampaignSettingsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("SmartCampaignSettingServiceClient",) diff --git a/google/ads/googleads/v15/services/services/smart_campaign_setting_service/transports/__init__.py b/google/ads/googleads/v15/services/services/smart_campaign_setting_service/transports/__init__.py new file mode 100644 index 000000000..d6904bb88 --- /dev/null +++ b/google/ads/googleads/v15/services/services/smart_campaign_setting_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[SmartCampaignSettingServiceTransport]] +_transport_registry["grpc"] = SmartCampaignSettingServiceGrpcTransport + +__all__ = ( + "SmartCampaignSettingServiceTransport", + "SmartCampaignSettingServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/smart_campaign_setting_service/transports/base.py b/google/ads/googleads/v15/services/services/smart_campaign_setting_service/transports/base.py new file mode 100644 index 000000000..197494f23 --- /dev/null +++ b/google/ads/googleads/v15/services/services/smart_campaign_setting_service/transports/base.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + smart_campaign_setting_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("SmartCampaignSettingServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/smart_campaign_setting_service/transports/grpc.py b/google/ads/googleads/v15/services/services/smart_campaign_setting_service/transports/grpc.py new file mode 100644 index 000000000..d86645d16 --- /dev/null +++ b/google/ads/googleads/v15/services/services/smart_campaign_setting_service/transports/grpc.py @@ -0,0 +1,310 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + smart_campaign_setting_service, +) +from .base import SmartCampaignSettingServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def get_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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("SmartCampaignSettingServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/__init__.py b/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/__init__.py new file mode 100644 index 000000000..855a170a6 --- /dev/null +++ b/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("SmartCampaignSuggestServiceClient",) diff --git a/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/client.py b/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/client.py new file mode 100644 index 000000000..8f34e3505 --- /dev/null +++ b/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/client.py @@ -0,0 +1,659 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + smart_campaign_suggest_service, +) +from .transports.base import ( + SmartCampaignSuggestServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import SmartCampaignSuggestServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, SmartCampaignSuggestServiceTransport): + # transport is a SmartCampaignSuggestServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsResponse: + r"""Returns BudgetOption suggestions. + + Args: + request (Union[google.ads.googleads.v15.services.types.SuggestSmartCampaignBudgetOptionsRequest, dict, None]): + The request object. Request message for + [SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.SuggestSmartCampaignBudgetOptionsResponse: + Response message for + [SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions][google.ads.googleads.v15.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. + # Minor optimization to avoid making a copy if the user passes + # in a smart_campaign_suggest_service.SuggestSmartCampaignBudgetOptionsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # 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, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> 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.v15.services.types.SuggestSmartCampaignAdRequest, dict, None]): + The request object. Request message for + [SmartCampaignSuggestService.SuggestSmartCampaignAd][google.ads.googleads.v15.services.SmartCampaignSuggestService.SuggestSmartCampaignAd]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.SuggestSmartCampaignAdResponse: + Response message for + [SmartCampaignSuggestService.SuggestSmartCampaignAd][google.ads.googleads.v15.services.SmartCampaignSuggestService.SuggestSmartCampaignAd]. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a smart_campaign_suggest_service.SuggestSmartCampaignAdRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, + smart_campaign_suggest_service.SuggestSmartCampaignAdRequest, + ): + request = ( + smart_campaign_suggest_service.SuggestSmartCampaignAdRequest( + 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_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),) + ), + ) + + # 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, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> smart_campaign_suggest_service.SuggestKeywordThemesResponse: + r"""Suggests keyword themes to advertise on. + + Args: + request (Union[google.ads.googleads.v15.services.types.SuggestKeywordThemesRequest, dict, None]): + The request object. Request message for + [SmartCampaignSuggestService.SuggestKeywordThemes][google.ads.googleads.v15.services.SmartCampaignSuggestService.SuggestKeywordThemes]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.SuggestKeywordThemesResponse: + Response message for + [SmartCampaignSuggestService.SuggestKeywordThemes][google.ads.googleads.v15.services.SmartCampaignSuggestService.SuggestKeywordThemes]. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a smart_campaign_suggest_service.SuggestKeywordThemesRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance( + request, smart_campaign_suggest_service.SuggestKeywordThemesRequest + ): + request = ( + smart_campaign_suggest_service.SuggestKeywordThemesRequest( + request + ) + ) + + # 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("SmartCampaignSuggestServiceClient",) diff --git a/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/transports/__init__.py b/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/transports/__init__.py new file mode 100644 index 000000000..163bd5e13 --- /dev/null +++ b/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[SmartCampaignSuggestServiceTransport]] +_transport_registry["grpc"] = SmartCampaignSuggestServiceGrpcTransport + +__all__ = ( + "SmartCampaignSuggestServiceTransport", + "SmartCampaignSuggestServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/transports/base.py b/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/transports/base.py new file mode 100644 index 000000000..089295a02 --- /dev/null +++ b/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/transports/base.py @@ -0,0 +1,200 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + smart_campaign_suggest_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("SmartCampaignSuggestServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/transports/grpc.py b/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/transports/grpc.py new file mode 100644 index 000000000..8e3563750 --- /dev/null +++ b/google/ads/googleads/v15/services/services/smart_campaign_suggest_service/transports/grpc.py @@ -0,0 +1,346 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + smart_campaign_suggest_service, +) +from .base import SmartCampaignSuggestServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("SmartCampaignSuggestServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/__init__.py b/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/__init__.py new file mode 100644 index 000000000..0456ba034 --- /dev/null +++ b/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("ThirdPartyAppAnalyticsLinkServiceClient",) diff --git a/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/client.py b/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/client.py new file mode 100644 index 000000000..78a2bbd32 --- /dev/null +++ b/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/client.py @@ -0,0 +1,502 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + third_party_app_analytics_link_service, +) +from .transports.base import ( + ThirdPartyAppAnalyticsLinkServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import ThirdPartyAppAnalyticsLinkServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, ThirdPartyAppAnalyticsLinkServiceTransport): + # transport is a ThirdPartyAppAnalyticsLinkServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.RegenerateShareableLinkIdRequest, dict, None]): + The request object. Request message for + [ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.RegenerateShareableLinkIdResponse: + Response message for + [ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId][google.ads.googleads.v15.services.ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId]. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a third_party_app_analytics_link_service.RegenerateShareableLinkIdRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("ThirdPartyAppAnalyticsLinkServiceClient",) diff --git a/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/transports/__init__.py b/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/transports/__init__.py new file mode 100644 index 000000000..91230b6a5 --- /dev/null +++ b/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ThirdPartyAppAnalyticsLinkServiceTransport]] +_transport_registry["grpc"] = ThirdPartyAppAnalyticsLinkServiceGrpcTransport + +__all__ = ( + "ThirdPartyAppAnalyticsLinkServiceTransport", + "ThirdPartyAppAnalyticsLinkServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/transports/base.py b/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/transports/base.py new file mode 100644 index 000000000..275830ffb --- /dev/null +++ b/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/transports/base.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + third_party_app_analytics_link_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("ThirdPartyAppAnalyticsLinkServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/transports/grpc.py b/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/transports/grpc.py new file mode 100644 index 000000000..674d35587 --- /dev/null +++ b/google/ads/googleads/v15/services/services/third_party_app_analytics_link_service/transports/grpc.py @@ -0,0 +1,291 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + third_party_app_analytics_link_service, +) +from .base import ( + ThirdPartyAppAnalyticsLinkServiceTransport, + DEFAULT_CLIENT_INFO, +) + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("ThirdPartyAppAnalyticsLinkServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/__init__.py b/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/__init__.py new file mode 100644 index 000000000..e337c3cfc --- /dev/null +++ b/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("TravelAssetSuggestionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/client.py b/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/client.py new file mode 100644 index 000000000..fd929b024 --- /dev/null +++ b/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/client.py @@ -0,0 +1,510 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import ( + travel_asset_suggestion_service, +) +from .transports.base import ( + TravelAssetSuggestionServiceTransport, + DEFAULT_CLIENT_INFO, +) +from .transports.grpc import TravelAssetSuggestionServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, TravelAssetSuggestionServiceTransport): + # transport is a TravelAssetSuggestionServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.SuggestTravelAssetsRequest, dict, None]): + The request object. Request message for + [TravelAssetSuggestionService.SuggestTravelAssets][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.SuggestTravelAssetsResponse: + Response message for + [TravelAssetSuggestionService.SuggestTravelAssets][google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, language_option]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a travel_asset_suggestion_service.SuggestTravelAssetsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("TravelAssetSuggestionServiceClient",) diff --git a/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/transports/__init__.py b/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/transports/__init__.py new file mode 100644 index 000000000..7a3991ae8 --- /dev/null +++ b/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[TravelAssetSuggestionServiceTransport]] +_transport_registry["grpc"] = TravelAssetSuggestionServiceGrpcTransport + +__all__ = ( + "TravelAssetSuggestionServiceTransport", + "TravelAssetSuggestionServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/transports/base.py b/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/transports/base.py new file mode 100644 index 000000000..32b2088ca --- /dev/null +++ b/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/transports/base.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import ( + travel_asset_suggestion_service, +) + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("TravelAssetSuggestionServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/transports/grpc.py b/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/transports/grpc.py new file mode 100644 index 000000000..3daad6631 --- /dev/null +++ b/google/ads/googleads/v15/services/services/travel_asset_suggestion_service/transports/grpc.py @@ -0,0 +1,282 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import ( + travel_asset_suggestion_service, +) +from .base import TravelAssetSuggestionServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("TravelAssetSuggestionServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/user_data_service/__init__.py b/google/ads/googleads/v15/services/services/user_data_service/__init__.py new file mode 100644 index 000000000..aecf09df5 --- /dev/null +++ b/google/ads/googleads/v15/services/services/user_data_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("UserDataServiceClient",) diff --git a/google/ads/googleads/v15/services/services/user_data_service/client.py b/google/ads/googleads/v15/services/services/user_data_service/client.py new file mode 100644 index 000000000..d002cf44e --- /dev/null +++ b/google/ads/googleads/v15/services/services/user_data_service/client.py @@ -0,0 +1,472 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import Dict, Optional, Sequence, Tuple, Type, Union, cast +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.services.types import user_data_service +from .transports.base import UserDataServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import UserDataServiceGrpcTransport + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, UserDataServiceTransport): + # transport is a UserDataServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.UploadUserDataRequest, dict, None]): + The request object. Request message for + [UserDataService.UploadUserData][google.ads.googleads.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.services.types.UploadUserDataResponse: + Response message for + [UserDataService.UploadUserData][google.ads.googleads.v15.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. + # Minor optimization to avoid making a copy if the user passes + # in a user_data_service.UploadUserDataRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("UserDataServiceClient",) diff --git a/google/ads/googleads/v15/services/services/user_data_service/transports/__init__.py b/google/ads/googleads/v15/services/services/user_data_service/transports/__init__.py new file mode 100644 index 000000000..b7702aa16 --- /dev/null +++ b/google/ads/googleads/v15/services/services/user_data_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[UserDataServiceTransport]] +_transport_registry["grpc"] = UserDataServiceGrpcTransport + +__all__ = ( + "UserDataServiceTransport", + "UserDataServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/user_data_service/transports/base.py b/google/ads/googleads/v15/services/services/user_data_service/transports/base.py new file mode 100644 index 000000000..78d69649f --- /dev/null +++ b/google/ads/googleads/v15/services/services/user_data_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import user_data_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("UserDataServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/user_data_service/transports/grpc.py b/google/ads/googleads/v15/services/services/user_data_service/transports/grpc.py new file mode 100644 index 000000000..2ad9c017d --- /dev/null +++ b/google/ads/googleads/v15/services/services/user_data_service/transports/grpc.py @@ -0,0 +1,286 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import user_data_service +from .base import UserDataServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("UserDataServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/services/user_list_service/__init__.py b/google/ads/googleads/v15/services/services/user_list_service/__init__.py new file mode 100644 index 000000000..63f1b4e32 --- /dev/null +++ b/google/ads/googleads/v15/services/services/user_list_service/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +__all__ = ("UserListServiceClient",) diff --git a/google/ads/googleads/v15/services/services/user_list_service/client.py b/google/ads/googleads/v15/services/services/user_list_service/client.py new file mode 100644 index 000000000..97aeeaf3e --- /dev/null +++ b/google/ads/googleads/v15/services/services/user_list_service/client.py @@ -0,0 +1,530 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Dict, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import pkg_resources + +from google.api_core import client_options as client_options_lib +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 + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object] # type: ignore + +from google.ads.googleads.v15.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 + + +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 + + 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") + + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @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 + + 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() + + @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 {} + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[Union[str, 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]]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. + (1) The ``api_endpoint`` property can be used to override the + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT + environment variable can also be used to override the endpoint: + "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). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS 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. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API 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. + """ + if isinstance(client_options, dict): + client_options = client_options_lib.from_dict(client_options) + if client_options is None: + client_options = client_options_lib.ClientOptions() + client_options = cast(client_options_lib.ClientOptions, client_options) + + # Create SSL credentials for mutual TLS if needed. + if os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") not in ( + "true", + "false", + ): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + use_client_cert = ( + os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true" + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_env == "never": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT + if is_mtls + else self.DEFAULT_ENDPOINT + ) + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, UserListServiceTransport): + # transport is a UserListServiceTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + ) + + 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, str]] = (), + ) -> 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.v15.services.types.MutateUserListsRequest, dict, None]): + The request object. Request message for + [UserListService.MutateUserLists][google.ads.googleads.v15.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.v15.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, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.ads.googleads.v15.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. + has_flattened_params = any([customer_id, operations]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a user_list_service.MutateUserListsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + 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),) + ), + ) + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("UserListServiceClient",) diff --git a/google/ads/googleads/v15/services/services/user_list_service/transports/__init__.py b/google/ads/googleads/v15/services/services/user_list_service/transports/__init__.py new file mode 100644 index 000000000..d70910865 --- /dev/null +++ b/google/ads/googleads/v15/services/services/user_list_service/transports/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[UserListServiceTransport]] +_transport_registry["grpc"] = UserListServiceGrpcTransport + +__all__ = ( + "UserListServiceTransport", + "UserListServiceGrpcTransport", +) diff --git a/google/ads/googleads/v15/services/services/user_list_service/transports/base.py b/google/ads/googleads/v15/services/services/user_list_service/transports/base.py new file mode 100644 index 000000000..970a200d5 --- /dev/null +++ b/google/ads/googleads/v15/services/services/user_list_service/transports/base.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES 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 +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.ads.googleads.v15.services.types import user_list_service + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution( + "google-ads", + ).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +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, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # 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 + + 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() + + +__all__ = ("UserListServiceTransport",) diff --git a/google/ads/googleads/v15/services/services/user_list_service/transports/grpc.py b/google/ads/googleads/v15/services/services/user_list_service/transports/grpc.py new file mode 100644 index 000000000..72daefca8 --- /dev/null +++ b/google/ads/googleads/v15/services/services/user_list_service/transports/grpc.py @@ -0,0 +1,283 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple + +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 + +import grpc # type: ignore + +from google.ads.googleads.v15.services.types import user_list_service +from .base import UserListServiceTransport, DEFAULT_CLIENT_INFO + + +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[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, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "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]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def 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.grpc_channel.unary_unary( + "/google.ads.googleads.v15.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.grpc_channel.close() + + +__all__ = ("UserListServiceGrpcTransport",) diff --git a/google/ads/googleads/v15/services/types/__init__.py b/google/ads/googleads/v15/services/types/__init__.py new file mode 100644 index 000000000..89a37dc92 --- /dev/null +++ b/google/ads/googleads/v15/services/types/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/v15/services/types/account_budget_proposal_service.py b/google/ads/googleads/v15/services/types/account_budget_proposal_service.py new file mode 100644 index 000000000..c05e00393 --- /dev/null +++ b/google/ads/googleads/v15/services/types/account_budget_proposal_service.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.resources.types import account_budget_proposal +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAccountBudgetProposalRequest", + "AccountBudgetProposalOperation", + "MutateAccountBudgetProposalResponse", + "MutateAccountBudgetProposalResult", + }, +) + + +class MutateAccountBudgetProposalRequest(proto.Message): + r"""Request message for + [AccountBudgetProposalService.MutateAccountBudgetProposal][google.ads.googleads.v15.services.AccountBudgetProposalService.MutateAccountBudgetProposal]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + operation (google.ads.googleads.v15.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.v15.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.v15.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/v15/services/types/account_link_service.py b/google/ads/googleads/v15/services/types/account_link_service.py new file mode 100644 index 000000000..75b4aa30b --- /dev/null +++ b/google/ads/googleads/v15/services/types/account_link_service.py @@ -0,0 +1,205 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "CreateAccountLinkRequest", + "CreateAccountLinkResponse", + "MutateAccountLinkRequest", + "AccountLinkOperation", + "MutateAccountLinkResponse", + "MutateAccountLinkResult", + }, +) + + +class CreateAccountLinkRequest(proto.Message): + r"""Request message for + [AccountLinkService.CreateAccountLink][google.ads.googleads.v15.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.v15.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.v15.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.v15.services.AccountLinkService.MutateAccountLink]. + + Attributes: + customer_id (str): + Required. The ID of the customer being + modified. + operation (google.ads.googleads.v15.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.v15.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.v15.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/v15/services/types/ad_group_ad_label_service.py b/google/ads/googleads/v15/services/types/ad_group_ad_label_service.py new file mode 100644 index 000000000..05e112a7a --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_group_ad_label_service.py @@ -0,0 +1,158 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import ad_group_ad_label +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdGroupAdLabelsRequest", + "AdGroupAdLabelOperation", + "MutateAdGroupAdLabelsResponse", + "MutateAdGroupAdLabelResult", + }, +) + + +class MutateAdGroupAdLabelsRequest(proto.Message): + r"""Request message for + [AdGroupAdLabelService.MutateAdGroupAdLabels][google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/ad_group_ad_service.py b/google/ads/googleads/v15/services/types/ad_group_ad_service.py new file mode 100644 index 000000000..6f1f3df7b --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_group_ad_service.py @@ -0,0 +1,208 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import policy +from google.ads.googleads.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdGroupAdsRequest", + "AdGroupAdOperation", + "MutateAdGroupAdsResponse", + "MutateAdGroupAdResult", + }, +) + + +class MutateAdGroupAdsRequest(proto.Message): + r"""Request message for + [AdGroupAdService.MutateAdGroupAds][google.ads.googleads.v15.services.AdGroupAdService.MutateAdGroupAds]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose ads + are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.common.types.PolicyValidationParameter): + Configuration for how policies are validated. + create (google.ads.googleads.v15.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.v15.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.v15.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.v15.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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/ad_group_asset_service.py b/google/ads/googleads/v15/services/types/ad_group_asset_service.py new file mode 100644 index 000000000..1e1dd490f --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_group_asset_service.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdGroupAssetsRequest", + "AdGroupAssetOperation", + "MutateAdGroupAssetsResponse", + "MutateAdGroupAssetResult", + }, +) + + +class MutateAdGroupAssetsRequest(proto.Message): + r"""Request message for + [AdGroupAssetService.MutateAdGroupAssets][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/ad_group_asset_set_service.py b/google/ads/googleads/v15/services/types/ad_group_asset_set_service.py new file mode 100644 index 000000000..d23df1aa0 --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_group_asset_set_service.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdGroupAssetSetsRequest", + "AdGroupAssetSetOperation", + "MutateAdGroupAssetSetsResponse", + "MutateAdGroupAssetSetResult", + }, +) + + +class MutateAdGroupAssetSetsRequest(proto.Message): + r"""Request message for + [AdGroupAssetSetService.MutateAdGroupAssetSets][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/ad_group_bid_modifier_service.py b/google/ads/googleads/v15/services/types/ad_group_bid_modifier_service.py new file mode 100644 index 000000000..9a30021df --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_group_bid_modifier_service.py @@ -0,0 +1,205 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdGroupBidModifiersRequest", + "AdGroupBidModifierOperation", + "MutateAdGroupBidModifiersResponse", + "MutateAdGroupBidModifierResult", + }, +) + + +class MutateAdGroupBidModifiersRequest(proto.Message): + r"""Request message for + [AdGroupBidModifierService.MutateAdGroupBidModifiers][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/ad_group_criterion_customizer_service.py b/google/ads/googleads/v15/services/types/ad_group_criterion_customizer_service.py new file mode 100644 index 000000000..43a91f06f --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_group_criterion_customizer_service.py @@ -0,0 +1,184 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdGroupCriterionCustomizersRequest", + "AdGroupCriterionCustomizerOperation", + "MutateAdGroupCriterionCustomizersResponse", + "MutateAdGroupCriterionCustomizerResult", + }, +) + + +class MutateAdGroupCriterionCustomizersRequest(proto.Message): + r"""Request message for + [AdGroupCriterionCustomizerService.MutateAdGroupCriterionCustomizers][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/ad_group_criterion_label_service.py b/google/ads/googleads/v15/services/types/ad_group_criterion_label_service.py new file mode 100644 index 000000000..90c327572 --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_group_criterion_label_service.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import ad_group_criterion_label +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdGroupCriterionLabelsRequest", + "AdGroupCriterionLabelOperation", + "MutateAdGroupCriterionLabelsResponse", + "MutateAdGroupCriterionLabelResult", + }, +) + + +class MutateAdGroupCriterionLabelsRequest(proto.Message): + r"""Request message for + [AdGroupCriterionLabelService.MutateAdGroupCriterionLabels][google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/ad_group_criterion_service.py b/google/ads/googleads/v15/services/types/ad_group_criterion_service.py new file mode 100644 index 000000000..e113a0340 --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_group_criterion_service.py @@ -0,0 +1,221 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import policy +from google.ads.googleads.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdGroupCriteriaRequest", + "AdGroupCriterionOperation", + "MutateAdGroupCriteriaResponse", + "MutateAdGroupCriterionResult", + }, +) + + +class MutateAdGroupCriteriaRequest(proto.Message): + r"""Request message for + [AdGroupCriterionService.MutateAdGroupCriteria][google.ads.googleads.v15.services.AdGroupCriterionService.MutateAdGroupCriteria]. + + Attributes: + customer_id (str): + Required. ID of the customer whose criteria + are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/ad_group_customizer_service.py b/google/ads/googleads/v15/services/types/ad_group_customizer_service.py new file mode 100644 index 000000000..9918e5aea --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_group_customizer_service.py @@ -0,0 +1,184 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdGroupCustomizersRequest", + "AdGroupCustomizerOperation", + "MutateAdGroupCustomizersResponse", + "MutateAdGroupCustomizerResult", + }, +) + + +class MutateAdGroupCustomizersRequest(proto.Message): + r"""Request message for + [AdGroupCustomizerService.MutateAdGroupCustomizers][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/ad_group_extension_setting_service.py b/google/ads/googleads/v15/services/types/ad_group_extension_setting_service.py new file mode 100644 index 000000000..5e48f02e8 --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_group_extension_setting_service.py @@ -0,0 +1,208 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_extension_setting as gagr_ad_group_extension_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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdGroupExtensionSettingsRequest", + "AdGroupExtensionSettingOperation", + "MutateAdGroupExtensionSettingsResponse", + "MutateAdGroupExtensionSettingResult", + }, +) + + +class MutateAdGroupExtensionSettingsRequest(proto.Message): + r"""Request message for + [AdGroupExtensionSettingService.MutateAdGroupExtensionSettings][google.ads.googleads.v15.services.AdGroupExtensionSettingService.MutateAdGroupExtensionSettings]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose ad + group extension settings are being modified. + operations (MutableSequence[google.ads.googleads.v15.services.types.AdGroupExtensionSettingOperation]): + Required. The list of operations to perform + on individual ad group extension 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. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence[ + "AdGroupExtensionSettingOperation" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupExtensionSettingOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class AdGroupExtensionSettingOperation(proto.Message): + r"""A single operation (create, update, remove) on an ad group + extension setting. + + 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. + response_content_type (google.ads.googleads.v15.enums.types.ResponseContentTypeEnum.ResponseContentType): + The response content type setting. Determines + whether the mutable resource or just the + resource name should be returned post mutation. + create (google.ads.googleads.v15.resources.types.AdGroupExtensionSetting): + Create operation: No resource name is + expected for the new ad group extension setting. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v15.resources.types.AdGroupExtensionSetting): + Update operation: The ad group extension + setting 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 + extension setting is expected, in this format: + + ``customers/{customer_id}/adGroupExtensionSettings/{ad_group_id}~{extension_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, + ) + response_content_type: gage_response_content_type.ResponseContentTypeEnum.ResponseContentType = proto.Field( + proto.ENUM, + number=5, + enum=gage_response_content_type.ResponseContentTypeEnum.ResponseContentType, + ) + create: gagr_ad_group_extension_setting.AdGroupExtensionSetting = ( + proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_ad_group_extension_setting.AdGroupExtensionSetting, + ) + ) + update: gagr_ad_group_extension_setting.AdGroupExtensionSetting = ( + proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_ad_group_extension_setting.AdGroupExtensionSetting, + ) + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateAdGroupExtensionSettingsResponse(proto.Message): + r"""Response message for an ad group extension setting 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.v15.services.types.MutateAdGroupExtensionSettingResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence[ + "MutateAdGroupExtensionSettingResult" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateAdGroupExtensionSettingResult", + ) + + +class MutateAdGroupExtensionSettingResult(proto.Message): + r"""The result for the ad group extension setting mutate. + Attributes: + resource_name (str): + Returned for successful operations. + ad_group_extension_setting (google.ads.googleads.v15.resources.types.AdGroupExtensionSetting): + The mutated AdGroupExtensionSetting 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_extension_setting: gagr_ad_group_extension_setting.AdGroupExtensionSetting = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad_group_extension_setting.AdGroupExtensionSetting, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/ad_group_feed_service.py b/google/ads/googleads/v15/services/types/ad_group_feed_service.py new file mode 100644 index 000000000..f41221d37 --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_group_feed_service.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_feed as gagr_ad_group_feed, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdGroupFeedsRequest", + "AdGroupFeedOperation", + "MutateAdGroupFeedsResponse", + "MutateAdGroupFeedResult", + }, +) + + +class MutateAdGroupFeedsRequest(proto.Message): + r"""Request message for + [AdGroupFeedService.MutateAdGroupFeeds][google.ads.googleads.v15.services.AdGroupFeedService.MutateAdGroupFeeds]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose ad + group feeds are being modified. + operations (MutableSequence[google.ads.googleads.v15.services.types.AdGroupFeedOperation]): + Required. The list of operations to perform + on individual ad group feeds. + 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.v15.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["AdGroupFeedOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupFeedOperation", + ) + 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 AdGroupFeedOperation(proto.Message): + r"""A single operation (create, update, remove) on an ad group + feed. + + 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.v15.resources.types.AdGroupFeed): + Create operation: No resource name is + expected for the new ad group feed. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v15.resources.types.AdGroupFeed): + Update operation: The ad group feed 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 + feed is expected, in this format: + + ``customers/{customer_id}/adGroupFeeds/{ad_group_id}~{feed_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_feed.AdGroupFeed = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_ad_group_feed.AdGroupFeed, + ) + update: gagr_ad_group_feed.AdGroupFeed = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_ad_group_feed.AdGroupFeed, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateAdGroupFeedsResponse(proto.Message): + r"""Response message for an ad group feed 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.v15.services.types.MutateAdGroupFeedResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateAdGroupFeedResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateAdGroupFeedResult", + ) + + +class MutateAdGroupFeedResult(proto.Message): + r"""The result for the ad group feed mutate. + Attributes: + resource_name (str): + Returned for successful operations. + ad_group_feed (google.ads.googleads.v15.resources.types.AdGroupFeed): + The mutated ad group feed 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_feed: gagr_ad_group_feed.AdGroupFeed = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_ad_group_feed.AdGroupFeed, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/ad_group_label_service.py b/google/ads/googleads/v15/services/types/ad_group_label_service.py new file mode 100644 index 000000000..369c42e24 --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_group_label_service.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import ad_group_label +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdGroupLabelsRequest", + "AdGroupLabelOperation", + "MutateAdGroupLabelsResponse", + "MutateAdGroupLabelResult", + }, +) + + +class MutateAdGroupLabelsRequest(proto.Message): + r"""Request message for + [AdGroupLabelService.MutateAdGroupLabels][google.ads.googleads.v15.services.AdGroupLabelService.MutateAdGroupLabels]. + + Attributes: + customer_id (str): + Required. ID of the customer whose ad group + labels are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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/v15/services/types/ad_group_service.py b/google/ads/googleads/v15/services/types/ad_group_service.py new file mode 100644 index 000000000..3f4fa8bda --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_group_service.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdGroupsRequest", + "AdGroupOperation", + "MutateAdGroupsResponse", + "MutateAdGroupResult", + }, +) + + +class MutateAdGroupsRequest(proto.Message): + r"""Request message for + [AdGroupService.MutateAdGroups][google.ads.googleads.v15.services.AdGroupService.MutateAdGroups]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose ad + groups are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/ad_parameter_service.py b/google/ads/googleads/v15/services/types/ad_parameter_service.py new file mode 100644 index 000000000..f4ea21193 --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_parameter_service.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAdParametersRequest", + "AdParameterOperation", + "MutateAdParametersResponse", + "MutateAdParameterResult", + }, +) + + +class MutateAdParametersRequest(proto.Message): + r"""Request message for + [AdParameterService.MutateAdParameters][google.ads.googleads.v15.services.AdParameterService.MutateAdParameters] + + Attributes: + customer_id (str): + Required. The ID of the customer whose ad + parameters are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/ad_service.py b/google/ads/googleads/v15/services/types/ad_service.py new file mode 100644 index 000000000..03b55b096 --- /dev/null +++ b/google/ads/googleads/v15/services/types/ad_service.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import policy +from google.ads.googleads.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "GetAdRequest", + "MutateAdsRequest", + "AdOperation", + "MutateAdsResponse", + "MutateAdResult", + }, +) + + +class GetAdRequest(proto.Message): + r"""Request message for + [AdService.GetAd][google.ads.googleads.v15.services.AdService.GetAd]. + + Attributes: + resource_name (str): + Required. The resource name of the ad to + fetch. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class MutateAdsRequest(proto.Message): + r"""Request message for + [AdService.MutateAds][google.ads.googleads.v15.services.AdService.MutateAds]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose ads + are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.common.types.PolicyValidationParameter): + Configuration for how policies are validated. + update (google.ads.googleads.v15.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.v15.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.v15.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/v15/services/types/asset_group_asset_service.py b/google/ads/googleads/v15/services/types/asset_group_asset_service.py new file mode 100644 index 000000000..e7aaaa364 --- /dev/null +++ b/google/ads/googleads/v15/services/types/asset_group_asset_service.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAssetGroupAssetsRequest", + "AssetGroupAssetOperation", + "MutateAssetGroupAssetsResponse", + "MutateAssetGroupAssetResult", + }, +) + + +class MutateAssetGroupAssetsRequest(proto.Message): + r"""Request message for + [AssetGroupAssetService.MutateAssetGroupAssets][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/asset_group_listing_group_filter_service.py b/google/ads/googleads/v15/services/types/asset_group_listing_group_filter_service.py new file mode 100644 index 000000000..45a487376 --- /dev/null +++ b/google/ads/googleads/v15/services/types/asset_group_listing_group_filter_service.py @@ -0,0 +1,189 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAssetGroupListingGroupFiltersRequest", + "AssetGroupListingGroupFilterOperation", + "MutateAssetGroupListingGroupFiltersResponse", + "MutateAssetGroupListingGroupFilterResult", + }, +) + + +class MutateAssetGroupListingGroupFiltersRequest(proto.Message): + r"""Request message for + [AssetGroupListingGroupFilterService.MutateAssetGroupListingGroupFilters][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/asset_group_service.py b/google/ads/googleads/v15/services/types/asset_group_service.py new file mode 100644 index 000000000..df0fb6b16 --- /dev/null +++ b/google/ads/googleads/v15/services/types/asset_group_service.py @@ -0,0 +1,163 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAssetGroupsRequest", + "AssetGroupOperation", + "MutateAssetGroupsResponse", + "MutateAssetGroupResult", + }, +) + + +class MutateAssetGroupsRequest(proto.Message): + r"""Request message for + [AssetGroupService.MutateAssetGroups][google.ads.googleads.v15.services.AssetGroupService.MutateAssetGroups]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose asset + groups are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/asset_group_signal_service.py b/google/ads/googleads/v15/services/types/asset_group_signal_service.py new file mode 100644 index 000000000..81c2fa0a8 --- /dev/null +++ b/google/ads/googleads/v15/services/types/asset_group_signal_service.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import policy +from google.ads.googleads.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAssetGroupSignalsRequest", + "AssetGroupSignalOperation", + "MutateAssetGroupSignalsResponse", + "MutateAssetGroupSignalResult", + }, +) + + +class MutateAssetGroupSignalsRequest(proto.Message): + r"""Request message for + [AssetGroupSignalService.MutateAssetGroupSignals][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/asset_service.py b/google/ads/googleads/v15/services/types/asset_service.py new file mode 100644 index 000000000..f1af944f6 --- /dev/null +++ b/google/ads/googleads/v15/services/types/asset_service.py @@ -0,0 +1,191 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAssetsRequest", + "AssetOperation", + "MutateAssetsResponse", + "MutateAssetResult", + }, +) + + +class MutateAssetsRequest(proto.Message): + r"""Request message for + [AssetService.MutateAssets][google.ads.googleads.v15.services.AssetService.MutateAssets] + + Attributes: + customer_id (str): + Required. The ID of the customer whose assets + are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/asset_set_asset_service.py b/google/ads/googleads/v15/services/types/asset_set_asset_service.py new file mode 100644 index 000000000..a744e2be6 --- /dev/null +++ b/google/ads/googleads/v15/services/types/asset_set_asset_service.py @@ -0,0 +1,176 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAssetSetAssetsRequest", + "AssetSetAssetOperation", + "MutateAssetSetAssetsResponse", + "MutateAssetSetAssetResult", + }, +) + + +class MutateAssetSetAssetsRequest(proto.Message): + r"""Request message for + [AssetSetAssetService.MutateAssetSetAssets][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/asset_set_service.py b/google/ads/googleads/v15/services/types/asset_set_service.py new file mode 100644 index 000000000..573ad5ab8 --- /dev/null +++ b/google/ads/googleads/v15/services/types/asset_set_service.py @@ -0,0 +1,194 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAssetSetsRequest", + "AssetSetOperation", + "MutateAssetSetsResponse", + "MutateAssetSetResult", + }, +) + + +class MutateAssetSetsRequest(proto.Message): + r"""Request message for + [AssetSetService.MutateAssetSets][google.ads.googleads.v15.services.AssetSetService.MutateAssetSets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose asset + sets are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/audience_insights_service.py b/google/ads/googleads/v15/services/types/audience_insights_service.py new file mode 100644 index 000000000..ec25a7ec5 --- /dev/null +++ b/google/ads/googleads/v15/services/types/audience_insights_service.py @@ -0,0 +1,1152 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import criteria +from google.ads.googleads.v15.common.types import dates +from google.ads.googleads.v15.enums.types import audience_insights_dimension + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "GenerateInsightsFinderReportRequest", + "GenerateInsightsFinderReportResponse", + "GenerateAudienceCompositionInsightsRequest", + "GenerateAudienceCompositionInsightsResponse", + "GenerateSuggestedTargetingInsightsRequest", + "GenerateSuggestedTargetingInsightsResponse", + "TargetingSuggestionMetrics", + "ListAudienceInsightsAttributesRequest", + "ListAudienceInsightsAttributesResponse", + "ListInsightsEligibleDatesRequest", + "ListInsightsEligibleDatesResponse", + "AudienceInsightsAttribute", + "AudienceInsightsTopic", + "AudienceInsightsEntity", + "AudienceInsightsCategory", + "AudienceInsightsDynamicLineup", + "BasicInsightsAudience", + "AudienceInsightsAttributeMetadata", + "YouTubeChannelAttributeMetadata", + "DynamicLineupAttributeMetadata", + "LocationAttributeMetadata", + "InsightsAudience", + "InsightsAudienceAttributeGroup", + "AudienceCompositionSection", + "AudienceCompositionAttributeCluster", + "AudienceCompositionMetrics", + "AudienceCompositionAttribute", + }, +) + + +class GenerateInsightsFinderReportRequest(proto.Message): + r"""Request message for + [AudienceInsightsService.GenerateInsightsFinderReport][google.ads.googleads.v15.services.AudienceInsightsService.GenerateInsightsFinderReport]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + baseline_audience (google.ads.googleads.v15.services.types.BasicInsightsAudience): + Required. A baseline audience for this + report, typically all people in a region. + specific_audience (google.ads.googleads.v15.services.types.BasicInsightsAudience): + 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. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + baseline_audience: "BasicInsightsAudience" = proto.Field( + proto.MESSAGE, + number=2, + message="BasicInsightsAudience", + ) + specific_audience: "BasicInsightsAudience" = proto.Field( + proto.MESSAGE, + number=3, + message="BasicInsightsAudience", + ) + customer_insights_group: str = proto.Field( + proto.STRING, + number=4, + ) + + +class GenerateInsightsFinderReportResponse(proto.Message): + r"""The response message for + [AudienceInsightsService.GenerateInsightsFinderReport][google.ads.googleads.v15.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.v15.services.AudienceInsightsService.GenerateAudienceCompositionInsights]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + audience (google.ads.googleads.v15.services.types.InsightsAudience): + Required. The audience of interest for which + insights are being requested. + baseline_audience (google.ads.googleads.v15.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.v15.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]): + Required. The audience dimensions for which + composition insights should be returned. + customer_insights_group (str): + The name of the customer being planned for. + This is a user-defined value. + """ + + 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, + ) + + +class GenerateAudienceCompositionInsightsResponse(proto.Message): + r"""Response message for + [AudienceInsightsService.GenerateAudienceCompositionInsights][google.ads.googleads.v15.services.AudienceInsightsService.GenerateAudienceCompositionInsights]. + + Attributes: + sections (MutableSequence[google.ads.googleads.v15.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.v15.services.AudienceInsightsService.GenerateSuggestedTargetingInsights]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + audience (google.ads.googleads.v15.services.types.InsightsAudience): + Required. The audience of interest for which + insights are being requested. + baseline_audience (google.ads.googleads.v15.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. + customer_insights_group (str): + Optional. The name of the customer being + planned for. This is a user-defined value. + """ + + 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=3, + message="InsightsAudience", + ) + data_month: str = proto.Field( + proto.STRING, + number=4, + ) + customer_insights_group: str = proto.Field( + proto.STRING, + number=5, + ) + + +class GenerateSuggestedTargetingInsightsResponse(proto.Message): + r"""Response message for + [AudienceInsightsService.GenerateSuggestedTargetingInsights][google.ads.googleads.v15.services.AudienceInsightsService.GenerateSuggestedTargetingInsights]. + + Attributes: + suggestions (MutableSequence[google.ads.googleads.v15.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.v15.services.types.AudienceInsightsAttributeMetadata]): + Suggested location targeting. These attributes all have + dimension GEO_TARGET_COUNTRY or SUB_COUNTRY_LOCATION + age_ranges (MutableSequence[google.ads.googleads.v15.common.types.AgeRangeInfo]): + Suggested age targeting; may be empty + indicating no age targeting. + gender (google.ads.googleads.v15.common.types.GenderInfo): + Suggested gender targeting. If present, this + attribute has dimension GENDER. + user_interests (MutableSequence[google.ads.googleads.v15.services.types.AudienceInsightsAttributeMetadata]): + Suggested audience segments to target. These attributes all + have dimension AFFINITY_USER_INTEREST or + IN_MARKET_USER_INTEREST + 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[ + "AudienceInsightsAttributeMetadata" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="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, + ) + user_interests: MutableSequence[ + "AudienceInsightsAttributeMetadata" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="AudienceInsightsAttributeMetadata", + ) + 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.v15.services.AudienceInsightsService.ListAudienceInsightsAttributes]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + dimensions (MutableSequence[google.ads.googleads.v15.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension]): + Required. The types of attributes to be + returned. + 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. + location_country_filters (MutableSequence[google.ads.googleads.v15.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. + """ + + 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, + ) + location_country_filters: MutableSequence[ + criteria.LocationInfo + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=criteria.LocationInfo, + ) + + +class ListAudienceInsightsAttributesResponse(proto.Message): + r"""Response message for + [AudienceInsightsService.ListAudienceInsightsAttributes][google.ads.googleads.v15.services.AudienceInsightsService.ListAudienceInsightsAttributes]. + + Attributes: + attributes (MutableSequence[google.ads.googleads.v15.services.types.AudienceInsightsAttributeMetadata]): + The attributes matching the search query. + """ + + attributes: MutableSequence[ + "AudienceInsightsAttributeMetadata" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="AudienceInsightsAttributeMetadata", + ) + + +class ListInsightsEligibleDatesRequest(proto.Message): + r"""Request message for + [AudienceInsightsService.ListInsightsEligibleDates][google.ads.googleads.v15.services.AudienceInsightsService.ListInsightsEligibleDates]. + + """ + + +class ListInsightsEligibleDatesResponse(proto.Message): + r"""Response message for + [AudienceInsightsService.ListInsightsEligibleDates][google.ads.googleads.v15.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.v15.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.v15.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 AudienceInsightsAttribute(proto.Message): + r"""An audience attribute that can be used to request insights + about the 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_range (google.ads.googleads.v15.common.types.AgeRangeInfo): + An audience attribute defined by an age + range. + + This field is a member of `oneof`_ ``attribute``. + gender (google.ads.googleads.v15.common.types.GenderInfo): + An audience attribute defined by a gender. + + This field is a member of `oneof`_ ``attribute``. + location (google.ads.googleads.v15.common.types.LocationInfo): + An audience attribute defined by a geographic + location. + + This field is a member of `oneof`_ ``attribute``. + user_interest (google.ads.googleads.v15.common.types.UserInterestInfo): + An Affinity or In-Market audience. + + This field is a member of `oneof`_ ``attribute``. + entity (google.ads.googleads.v15.services.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.v15.services.types.AudienceInsightsCategory): + An audience attribute defined by interest in + a Product & Service category. + + This field is a member of `oneof`_ ``attribute``. + dynamic_lineup (google.ads.googleads.v15.services.types.AudienceInsightsDynamicLineup): + A YouTube Dynamic Lineup + + This field is a member of `oneof`_ ``attribute``. + parental_status (google.ads.googleads.v15.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.v15.common.types.IncomeRangeInfo): + A household income percentile range. + + This field is a member of `oneof`_ ``attribute``. + youtube_channel (google.ads.googleads.v15.common.types.YouTubeChannelInfo): + A YouTube channel. + + 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", + ) + dynamic_lineup: "AudienceInsightsDynamicLineup" = proto.Field( + proto.MESSAGE, + number=7, + oneof="attribute", + message="AudienceInsightsDynamicLineup", + ) + 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, + ) + + +class AudienceInsightsTopic(proto.Message): + r"""An entity or category representing a topic that defines 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: + entity (google.ads.googleads.v15.services.types.AudienceInsightsEntity): + A Knowledge Graph entity + + This field is a member of `oneof`_ ``topic``. + category (google.ads.googleads.v15.services.types.AudienceInsightsCategory): + A Product & Service category + + This field is a member of `oneof`_ ``topic``. + """ + + entity: "AudienceInsightsEntity" = proto.Field( + proto.MESSAGE, + number=1, + oneof="topic", + message="AudienceInsightsEntity", + ) + category: "AudienceInsightsCategory" = proto.Field( + proto.MESSAGE, + number=2, + oneof="topic", + message="AudienceInsightsCategory", + ) + + +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 AudienceInsightsDynamicLineup(proto.Message): + r"""A YouTube Dynamic Lineup. + Attributes: + dynamic_lineup_id (str): + Required. The numeric ID of the dynamic + lineup. + """ + + dynamic_lineup_id: str = proto.Field( + proto.STRING, + number=1, + ) + + +class BasicInsightsAudience(proto.Message): + r"""A description of an audience used for requesting insights. + Attributes: + country_location (MutableSequence[google.ads.googleads.v15.common.types.LocationInfo]): + Required. The countries for this audience. + sub_country_locations (MutableSequence[google.ads.googleads.v15.common.types.LocationInfo]): + Sub-country geographic location attributes. + If present, each of these must be contained in + one of the countries in this audience. + gender (google.ads.googleads.v15.common.types.GenderInfo): + Gender for the audience. If absent, the + audience does not restrict by gender. + age_ranges (MutableSequence[google.ads.googleads.v15.common.types.AgeRangeInfo]): + Age ranges for the audience. If absent, the + audience represents all people over 18 that + match the other attributes. + user_interests (MutableSequence[google.ads.googleads.v15.common.types.UserInterestInfo]): + User interests defining this audience. + Affinity and In-Market audiences are supported. + topics (MutableSequence[google.ads.googleads.v15.services.types.AudienceInsightsTopic]): + Topics, represented by Knowledge Graph + entities and/or Product & Service categories, + that this audience is interested in. + """ + + country_location: 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, + ) + user_interests: MutableSequence[ + criteria.UserInterestInfo + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=criteria.UserInterestInfo, + ) + topics: MutableSequence["AudienceInsightsTopic"] = proto.RepeatedField( + proto.MESSAGE, + number=6, + message="AudienceInsightsTopic", + ) + + +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.v15.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension): + The type of the attribute. + attribute (google.ads.googleads.v15.services.types.AudienceInsightsAttribute): + The attribute itself. + display_name (str): + The human-readable name of the attribute. + score (float): + A relevance score for this attribute, between + 0 and 1. + 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". + youtube_channel_metadata (google.ads.googleads.v15.services.types.YouTubeChannelAttributeMetadata): + Special metadata for a YouTube channel. + + This field is a member of `oneof`_ ``dimension_metadata``. + dynamic_attribute_metadata (google.ads.googleads.v15.services.types.DynamicLineupAttributeMetadata): + Special metadata for a YouTube Dynamic + Lineup. + + This field is a member of `oneof`_ ``dimension_metadata``. + location_attribute_metadata (google.ads.googleads.v15.services.types.LocationAttributeMetadata): + Special metadata for a Location. + + 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, + ) + score: float = proto.Field( + proto.DOUBLE, + number=4, + ) + display_info: str = proto.Field( + proto.STRING, + number=5, + ) + youtube_channel_metadata: "YouTubeChannelAttributeMetadata" = proto.Field( + proto.MESSAGE, + number=6, + oneof="dimension_metadata", + message="YouTubeChannelAttributeMetadata", + ) + dynamic_attribute_metadata: "DynamicLineupAttributeMetadata" = proto.Field( + proto.MESSAGE, + number=7, + oneof="dimension_metadata", + message="DynamicLineupAttributeMetadata", + ) + location_attribute_metadata: "LocationAttributeMetadata" = proto.Field( + proto.MESSAGE, + number=8, + oneof="dimension_metadata", + message="LocationAttributeMetadata", + ) + + +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 DynamicLineupAttributeMetadata(proto.Message): + r"""Metadata associated with a Dynamic Lineup attribute. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + inventory_country (google.ads.googleads.v15.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.v15.services.types.DynamicLineupAttributeMetadata.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.v15.common.types.YouTubeChannelInfo): + A YouTube channel. + display_name (str): + The name of the sample channel. + youtube_channel_metadata (google.ads.googleads.v15.services.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.v15.common.types.LocationInfo): + The country location of the sub country + location. + """ + + country_location: criteria.LocationInfo = proto.Field( + proto.MESSAGE, + number=1, + message=criteria.LocationInfo, + ) + + +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.v15.common.types.LocationInfo]): + Required. The countries for the audience. + sub_country_locations (MutableSequence[google.ads.googleads.v15.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.v15.common.types.GenderInfo): + Gender for the audience. If absent, the + audience does not restrict by gender. + age_ranges (MutableSequence[google.ads.googleads.v15.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.v15.common.types.ParentalStatusInfo): + Parental status for the audience. If absent, + the audience does not restrict by parental + status. + income_ranges (MutableSequence[google.ads.googleads.v15.common.types.IncomeRangeInfo]): + Household income percentile ranges for the + audience. If absent, the audience does not + restrict by household income range. + dynamic_lineups (MutableSequence[google.ads.googleads.v15.services.types.AudienceInsightsDynamicLineup]): + Dynamic lineups representing the YouTube + content viewed by the audience. + topic_audience_combinations (MutableSequence[google.ads.googleads.v15.services.types.InsightsAudienceAttributeGroup]): + A combination of entity, category and user + interest attributes defining the audience. The + combination has a logical AND-of-ORs structure: + Attributes within each + InsightsAudienceAttributeGroup are combined with + OR, and the combinations themselves are combined + together with AND. For example, the expression + (Entity OR Affinity) AND (In-Market OR Category) + can be formed using two + InsightsAudienceAttributeGroups with two + Attributes each. + """ + + 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, + ) + dynamic_lineups: MutableSequence[ + "AudienceInsightsDynamicLineup" + ] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message="AudienceInsightsDynamicLineup", + ) + topic_audience_combinations: MutableSequence[ + "InsightsAudienceAttributeGroup" + ] = proto.RepeatedField( + proto.MESSAGE, + number=8, + message="InsightsAudienceAttributeGroup", + ) + + +class InsightsAudienceAttributeGroup(proto.Message): + r"""A list of AudienceInsightsAttributes. + Attributes: + attributes (MutableSequence[google.ads.googleads.v15.services.types.AudienceInsightsAttribute]): + Required. A collection of audience attributes + to be combined with logical OR. Attributes need + not all be the same dimension. Only Knowledge + Graph entities, Product & Service Categories, + and Affinity and In-Market audiences are + supported in this context. + """ + + attributes: MutableSequence[ + "AudienceInsightsAttribute" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="AudienceInsightsAttribute", + ) + + +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.v15.enums.types.AudienceInsightsDimensionEnum.AudienceInsightsDimension): + The type of the attributes in this section. + top_attributes (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.services.types.AudienceInsightsAttributeMetadata): + The attribute with its metadata. + metrics (google.ads.googleads.v15.services.types.AudienceCompositionMetrics): + Share and index metrics for the attribute. + """ + + attribute_metadata: "AudienceInsightsAttributeMetadata" = proto.Field( + proto.MESSAGE, + number=1, + message="AudienceInsightsAttributeMetadata", + ) + metrics: "AudienceCompositionMetrics" = proto.Field( + proto.MESSAGE, + number=2, + message="AudienceCompositionMetrics", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/audience_service.py b/google/ads/googleads/v15/services/types/audience_service.py new file mode 100644 index 000000000..69a782aa5 --- /dev/null +++ b/google/ads/googleads/v15/services/types/audience_service.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateAudiencesRequest", + "MutateAudiencesResponse", + "AudienceOperation", + "MutateAudienceResult", + }, +) + + +class MutateAudiencesRequest(proto.Message): + r"""Request message for + [AudienceService.MutateAudiences][google.ads.googleads.v15.services.AudienceService.MutateAudiences]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + audiences are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/batch_job_service.py b/google/ads/googleads/v15/services/types/batch_job_service.py new file mode 100644 index 000000000..cb96e5959 --- /dev/null +++ b/google/ads/googleads/v15/services/types/batch_job_service.py @@ -0,0 +1,329 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import batch_job +from google.ads.googleads.v15.services.types import google_ads_service +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateBatchJobRequest", + "BatchJobOperation", + "MutateBatchJobResponse", + "MutateBatchJobResult", + "RunBatchJobRequest", + "AddBatchJobOperationsRequest", + "AddBatchJobOperationsResponse", + "ListBatchJobResultsRequest", + "ListBatchJobResultsResponse", + "BatchJobResult", + }, +) + + +class MutateBatchJobRequest(proto.Message): + r"""Request message for + [BatchJobService.MutateBatchJob][google.ads.googleads.v15.services.BatchJobService.MutateBatchJob]. + + Attributes: + customer_id (str): + Required. The ID of the customer for which to + create a batch job. + operation (google.ads.googleads.v15.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.v15.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.v15.services.BatchJobService.MutateBatchJob]. + + Attributes: + result (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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. When a page request is too large, the + server may decide to further limit the number of + returned resources. + response_content_type (google.ads.googleads.v15.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.v15.services.BatchJobService.ListBatchJobResults]. + + Attributes: + results (MutableSequence[google.ads.googleads.v15.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.v15.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/v15/services/types/bidding_data_exclusion_service.py b/google/ads/googleads/v15/services/types/bidding_data_exclusion_service.py new file mode 100644 index 000000000..30cda413a --- /dev/null +++ b/google/ads/googleads/v15/services/types/bidding_data_exclusion_service.py @@ -0,0 +1,205 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateBiddingDataExclusionsRequest", + "BiddingDataExclusionOperation", + "MutateBiddingDataExclusionsResponse", + "MutateBiddingDataExclusionsResult", + }, +) + + +class MutateBiddingDataExclusionsRequest(proto.Message): + r"""Request message for + [BiddingDataExclusionService.MutateBiddingDataExclusions][google.ads.googleads.v15.services.BiddingDataExclusionService.MutateBiddingDataExclusions]. + + Attributes: + customer_id (str): + Required. ID of the customer whose data + exclusions are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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 exlusions 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.v15.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.v15.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/v15/services/types/bidding_seasonality_adjustment_service.py b/google/ads/googleads/v15/services/types/bidding_seasonality_adjustment_service.py new file mode 100644 index 000000000..3e2899ba9 --- /dev/null +++ b/google/ads/googleads/v15/services/types/bidding_seasonality_adjustment_service.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateBiddingSeasonalityAdjustmentsRequest", + "BiddingSeasonalityAdjustmentOperation", + "MutateBiddingSeasonalityAdjustmentsResponse", + "MutateBiddingSeasonalityAdjustmentsResult", + }, +) + + +class MutateBiddingSeasonalityAdjustmentsRequest(proto.Message): + r"""Request message for + [BiddingSeasonalityAdjustmentService.MutateBiddingSeasonalityAdjustments][google.ads.googleads.v15.services.BiddingSeasonalityAdjustmentService.MutateBiddingSeasonalityAdjustments]. + + Attributes: + customer_id (str): + Required. ID of the customer whose + seasonality adjustments are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/bidding_strategy_service.py b/google/ads/googleads/v15/services/types/bidding_strategy_service.py new file mode 100644 index 000000000..d20268414 --- /dev/null +++ b/google/ads/googleads/v15/services/types/bidding_strategy_service.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateBiddingStrategiesRequest", + "BiddingStrategyOperation", + "MutateBiddingStrategiesResponse", + "MutateBiddingStrategyResult", + }, +) + + +class MutateBiddingStrategiesRequest(proto.Message): + r"""Request message for + [BiddingStrategyService.MutateBiddingStrategies][google.ads.googleads.v15.services.BiddingStrategyService.MutateBiddingStrategies]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + bidding strategies are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/billing_setup_service.py b/google/ads/googleads/v15/services/types/billing_setup_service.py new file mode 100644 index 000000000..77ba86c6c --- /dev/null +++ b/google/ads/googleads/v15/services/types/billing_setup_service.py @@ -0,0 +1,124 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.resources.types import billing_setup + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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/v15/services/types/brand_suggestion_service.py b/google/ads/googleads/v15/services/types/brand_suggestion_service.py new file mode 100644 index 000000000..ae9108bf5 --- /dev/null +++ b/google/ads/googleads/v15/services/types/brand_suggestion_service.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import brand_state + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "SuggestBrandsRequest", + "SuggestBrandsResponse", + "BrandSuggestion", + }, +) + + +class SuggestBrandsRequest(proto.Message): + r"""Request message for + [BrandSuggestionService.SuggestBrands][google.ads.googleads.v15.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.v15.services.BrandSuggestionService.SuggestBrands]. + + Attributes: + brands (MutableSequence[google.ads.googleads.v15.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.v15.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/v15/services/types/campaign_asset_service.py b/google/ads/googleads/v15/services/types/campaign_asset_service.py new file mode 100644 index 000000000..32863051b --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_asset_service.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignAssetsRequest", + "CampaignAssetOperation", + "MutateCampaignAssetsResponse", + "MutateCampaignAssetResult", + }, +) + + +class MutateCampaignAssetsRequest(proto.Message): + r"""Request message for + [CampaignAssetService.MutateCampaignAssets][google.ads.googleads.v15.services.CampaignAssetService.MutateCampaignAssets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign assets are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/campaign_asset_set_service.py b/google/ads/googleads/v15/services/types/campaign_asset_set_service.py new file mode 100644 index 000000000..bb4b25377 --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_asset_set_service.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignAssetSetsRequest", + "CampaignAssetSetOperation", + "MutateCampaignAssetSetsResponse", + "MutateCampaignAssetSetResult", + }, +) + + +class MutateCampaignAssetSetsRequest(proto.Message): + r"""Request message for + [CampaignAssetSetService.MutateCampaignAssetSets][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/campaign_bid_modifier_service.py b/google/ads/googleads/v15/services/types/campaign_bid_modifier_service.py new file mode 100644 index 000000000..e3dd0e799 --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_bid_modifier_service.py @@ -0,0 +1,205 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignBidModifiersRequest", + "CampaignBidModifierOperation", + "MutateCampaignBidModifiersResponse", + "MutateCampaignBidModifierResult", + }, +) + + +class MutateCampaignBidModifiersRequest(proto.Message): + r"""Request message for + [CampaignBidModifierService.MutateCampaignBidModifiers][google.ads.googleads.v15.services.CampaignBidModifierService.MutateCampaignBidModifiers]. + + Attributes: + customer_id (str): + Required. ID of the customer whose campaign + bid modifiers are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/campaign_budget_service.py b/google/ads/googleads/v15/services/types/campaign_budget_service.py new file mode 100644 index 000000000..2ae865113 --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_budget_service.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignBudgetsRequest", + "CampaignBudgetOperation", + "MutateCampaignBudgetsResponse", + "MutateCampaignBudgetResult", + }, +) + + +class MutateCampaignBudgetsRequest(proto.Message): + r"""Request message for + [CampaignBudgetService.MutateCampaignBudgets][google.ads.googleads.v15.services.CampaignBudgetService.MutateCampaignBudgets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign budgets are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/campaign_conversion_goal_service.py b/google/ads/googleads/v15/services/types/campaign_conversion_goal_service.py new file mode 100644 index 000000000..919665b2c --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_conversion_goal_service.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import campaign_conversion_goal +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignConversionGoalsRequest", + "CampaignConversionGoalOperation", + "MutateCampaignConversionGoalsResponse", + "MutateCampaignConversionGoalResult", + }, +) + + +class MutateCampaignConversionGoalsRequest(proto.Message): + r"""Request message for + [CampaignConversionGoalService.MutateCampaignConversionGoals][google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/campaign_criterion_service.py b/google/ads/googleads/v15/services/types/campaign_criterion_service.py new file mode 100644 index 000000000..95050842f --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_criterion_service.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignCriteriaRequest", + "CampaignCriterionOperation", + "MutateCampaignCriteriaResponse", + "MutateCampaignCriterionResult", + }, +) + + +class MutateCampaignCriteriaRequest(proto.Message): + r"""Request message for + [CampaignCriterionService.MutateCampaignCriteria][google.ads.googleads.v15.services.CampaignCriterionService.MutateCampaignCriteria]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + criteria are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.resources.types.CampaignCriterion): + 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}/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.v15.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.v15.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/v15/services/types/campaign_customizer_service.py b/google/ads/googleads/v15/services/types/campaign_customizer_service.py new file mode 100644 index 000000000..74c35689a --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_customizer_service.py @@ -0,0 +1,184 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import ( + campaign_customizer as gagr_campaign_customizer, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignCustomizersRequest", + "CampaignCustomizerOperation", + "MutateCampaignCustomizersResponse", + "MutateCampaignCustomizerResult", + }, +) + + +class MutateCampaignCustomizersRequest(proto.Message): + r"""Request message for + [CampaignCustomizerService.MutateCampaignCustomizers][google.ads.googleads.v15.services.CampaignCustomizerService.MutateCampaignCustomizers]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign customizers are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/campaign_draft_service.py b/google/ads/googleads/v15/services/types/campaign_draft_service.py new file mode 100644 index 000000000..d0075673c --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_draft_service.py @@ -0,0 +1,290 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignDraftsRequest", + "PromoteCampaignDraftRequest", + "CampaignDraftOperation", + "MutateCampaignDraftsResponse", + "MutateCampaignDraftResult", + "ListCampaignDraftAsyncErrorsRequest", + "ListCampaignDraftAsyncErrorsResponse", + }, +) + + +class MutateCampaignDraftsRequest(proto.Message): + r"""Request message for + [CampaignDraftService.MutateCampaignDrafts][google.ads.googleads.v15.services.CampaignDraftService.MutateCampaignDrafts]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign drafts are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/campaign_extension_setting_service.py b/google/ads/googleads/v15/services/types/campaign_extension_setting_service.py new file mode 100644 index 000000000..1f4079e17 --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_extension_setting_service.py @@ -0,0 +1,208 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import ( + campaign_extension_setting as gagr_campaign_extension_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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignExtensionSettingsRequest", + "CampaignExtensionSettingOperation", + "MutateCampaignExtensionSettingsResponse", + "MutateCampaignExtensionSettingResult", + }, +) + + +class MutateCampaignExtensionSettingsRequest(proto.Message): + r"""Request message for + [CampaignExtensionSettingService.MutateCampaignExtensionSettings][google.ads.googleads.v15.services.CampaignExtensionSettingService.MutateCampaignExtensionSettings]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign extension settings are being modified. + operations (MutableSequence[google.ads.googleads.v15.services.types.CampaignExtensionSettingOperation]): + Required. The list of operations to perform + on individual campaign extension 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.v15.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[ + "CampaignExtensionSettingOperation" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignExtensionSettingOperation", + ) + 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 CampaignExtensionSettingOperation(proto.Message): + r"""A single operation (create, update, remove) on a campaign + extension setting. + + 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.v15.resources.types.CampaignExtensionSetting): + Create operation: No resource name is + expected for the new campaign extension setting. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v15.resources.types.CampaignExtensionSetting): + Update operation: The campaign extension + setting 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 + extension setting is expected, in this format: + + ``customers/{customer_id}/campaignExtensionSettings/{campaign_id}~{extension_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_extension_setting.CampaignExtensionSetting = ( + proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_campaign_extension_setting.CampaignExtensionSetting, + ) + ) + update: gagr_campaign_extension_setting.CampaignExtensionSetting = ( + proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_campaign_extension_setting.CampaignExtensionSetting, + ) + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateCampaignExtensionSettingsResponse(proto.Message): + r"""Response message for a campaign extension setting 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.v15.services.types.MutateCampaignExtensionSettingResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence[ + "MutateCampaignExtensionSettingResult" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCampaignExtensionSettingResult", + ) + + +class MutateCampaignExtensionSettingResult(proto.Message): + r"""The result for the campaign extension setting mutate. + Attributes: + resource_name (str): + Returned for successful operations. + campaign_extension_setting (google.ads.googleads.v15.resources.types.CampaignExtensionSetting): + The mutated campaign extension 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, + ) + campaign_extension_setting: gagr_campaign_extension_setting.CampaignExtensionSetting = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_campaign_extension_setting.CampaignExtensionSetting, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/campaign_feed_service.py b/google/ads/googleads/v15/services/types/campaign_feed_service.py new file mode 100644 index 000000000..529a9991b --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_feed_service.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import ( + campaign_feed as gagr_campaign_feed, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignFeedsRequest", + "CampaignFeedOperation", + "MutateCampaignFeedsResponse", + "MutateCampaignFeedResult", + }, +) + + +class MutateCampaignFeedsRequest(proto.Message): + r"""Request message for + [CampaignFeedService.MutateCampaignFeeds][google.ads.googleads.v15.services.CampaignFeedService.MutateCampaignFeeds]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign feeds are being modified. + operations (MutableSequence[google.ads.googleads.v15.services.types.CampaignFeedOperation]): + Required. The list of operations to perform + on individual campaign feeds. + 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.v15.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["CampaignFeedOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CampaignFeedOperation", + ) + 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 CampaignFeedOperation(proto.Message): + r"""A single operation (create, update, remove) on a campaign + feed. + + 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.v15.resources.types.CampaignFeed): + Create operation: No resource name is + expected for the new campaign feed. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v15.resources.types.CampaignFeed): + Update operation: The campaign feed 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 + feed is expected, in this format: + + ``customers/{customer_id}/campaignFeeds/{campaign_id}~{feed_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_feed.CampaignFeed = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_campaign_feed.CampaignFeed, + ) + update: gagr_campaign_feed.CampaignFeed = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_campaign_feed.CampaignFeed, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateCampaignFeedsResponse(proto.Message): + r"""Response message for a campaign feed 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.v15.services.types.MutateCampaignFeedResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCampaignFeedResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCampaignFeedResult", + ) + + +class MutateCampaignFeedResult(proto.Message): + r"""The result for the campaign feed mutate. + Attributes: + resource_name (str): + Returned for successful operations. + campaign_feed (google.ads.googleads.v15.resources.types.CampaignFeed): + The mutated campaign feed 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_feed: gagr_campaign_feed.CampaignFeed = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_campaign_feed.CampaignFeed, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/campaign_group_service.py b/google/ads/googleads/v15/services/types/campaign_group_service.py new file mode 100644 index 000000000..78df1abac --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_group_service.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignGroupsRequest", + "CampaignGroupOperation", + "MutateCampaignGroupsResponse", + "MutateCampaignGroupResult", + }, +) + + +class MutateCampaignGroupsRequest(proto.Message): + r"""Request message for + [CampaignGroupService.MutateCampaignGroups][google.ads.googleads.v15.services.CampaignGroupService.MutateCampaignGroups]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign groups are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/campaign_label_service.py b/google/ads/googleads/v15/services/types/campaign_label_service.py new file mode 100644 index 000000000..b11cca816 --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_label_service.py @@ -0,0 +1,157 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import campaign_label +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignLabelsRequest", + "CampaignLabelOperation", + "MutateCampaignLabelsResponse", + "MutateCampaignLabelResult", + }, +) + + +class MutateCampaignLabelsRequest(proto.Message): + r"""Request message for + [CampaignLabelService.MutateCampaignLabels][google.ads.googleads.v15.services.CampaignLabelService.MutateCampaignLabels]. + + Attributes: + customer_id (str): + Required. ID of the customer whose + campaign-label relationships are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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/v15/services/types/campaign_lifecycle_goal_service.py b/google/ads/googleads/v15/services/types/campaign_lifecycle_goal_service.py new file mode 100644 index 000000000..e3dc7e336 --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_lifecycle_goal_service.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.resources.types import campaign_lifecycle_goal +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "ConfigureCampaignLifecycleGoalsRequest", + "CampaignLifecycleGoalOperation", + "ConfigureCampaignLifecycleGoalsResponse", + "ConfigureCampaignLifecycleGoalsResult", + }, +) + + +class ConfigureCampaignLifecycleGoalsRequest(proto.Message): + r"""Request message for + [CampaignLifecycleService.configureCampaignLifecycleGoals][]. + + Attributes: + customer_id (str): + Required. The ID of the customer performing + the upload. + operation (google.ads.googleads.v15.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. + .. _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.v15.resources.types.CampaignLifecycleGoal): + Create operation: to create a new campaign + lifecycle goal or update an existing campaign + lifecycle goal. When creating a new campaign + lifecycle goal, all required fields, including + campaign field, needs to be set. Resource name + and field mask needs to be empty. When updating + an existing campaign lifecycle goal, resource + name and field mask need to be set, and campaign + field needs to be empty. Partial update based on + field mask is supported when updating an + existing campaign 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: campaign_lifecycle_goal.CampaignLifecycleGoal = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=campaign_lifecycle_goal.CampaignLifecycleGoal, + ) + + +class ConfigureCampaignLifecycleGoalsResponse(proto.Message): + r"""Response message for + [CampaignLifecycleService.configureCampaignLifecycleGoals][]. + + Attributes: + result (google.ads.googleads.v15.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/v15/services/types/campaign_service.py b/google/ads/googleads/v15/services/types/campaign_service.py new file mode 100644 index 000000000..0cfe746c6 --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_service.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignsRequest", + "CampaignOperation", + "MutateCampaignsResponse", + "MutateCampaignResult", + }, +) + + +class MutateCampaignsRequest(proto.Message): + r"""Request message for + [CampaignService.MutateCampaigns][google.ads.googleads.v15.services.CampaignService.MutateCampaigns]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaigns are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/campaign_shared_set_service.py b/google/ads/googleads/v15/services/types/campaign_shared_set_service.py new file mode 100644 index 000000000..8485ab076 --- /dev/null +++ b/google/ads/googleads/v15/services/types/campaign_shared_set_service.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCampaignSharedSetsRequest", + "CampaignSharedSetOperation", + "MutateCampaignSharedSetsResponse", + "MutateCampaignSharedSetResult", + }, +) + + +class MutateCampaignSharedSetsRequest(proto.Message): + r"""Request message for + [CampaignSharedSetService.MutateCampaignSharedSets][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/conversion_action_service.py b/google/ads/googleads/v15/services/types/conversion_action_service.py new file mode 100644 index 000000000..9cb64359c --- /dev/null +++ b/google/ads/googleads/v15/services/types/conversion_action_service.py @@ -0,0 +1,205 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateConversionActionsRequest", + "ConversionActionOperation", + "MutateConversionActionsResponse", + "MutateConversionActionResult", + }, +) + + +class MutateConversionActionsRequest(proto.Message): + r"""Request message for + [ConversionActionService.MutateConversionActions][google.ads.googleads.v15.services.ConversionActionService.MutateConversionActions]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + conversion actions are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/conversion_adjustment_upload_service.py b/google/ads/googleads/v15/services/types/conversion_adjustment_upload_service.py new file mode 100644 index 000000000..4638b49ff --- /dev/null +++ b/google/ads/googleads/v15/services/types/conversion_adjustment_upload_service.py @@ -0,0 +1,383 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import offline_user_data +from google.ads.googleads.v15.enums.types import conversion_adjustment_type +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "UploadConversionAdjustmentsRequest", + "UploadConversionAdjustmentsResponse", + "ConversionAdjustment", + "RestatementValue", + "GclidDateTimePair", + "ConversionAdjustmentResult", + }, +) + + +class UploadConversionAdjustmentsRequest(proto.Message): + r"""Request message for + [ConversionAdjustmentUploadService.UploadConversionAdjustments][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.enums.types.ConversionAdjustmentTypeEnum.ConversionAdjustmentType): + The adjustment type. + restatement_value (google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/conversion_custom_variable_service.py b/google/ads/googleads/v15/services/types/conversion_custom_variable_service.py new file mode 100644 index 000000000..1fd58ac6e --- /dev/null +++ b/google/ads/googleads/v15/services/types/conversion_custom_variable_service.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateConversionCustomVariablesRequest", + "ConversionCustomVariableOperation", + "MutateConversionCustomVariablesResponse", + "MutateConversionCustomVariableResult", + }, +) + + +class MutateConversionCustomVariablesRequest(proto.Message): + r"""Request message for + [ConversionCustomVariableService.MutateConversionCustomVariables][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/conversion_goal_campaign_config_service.py b/google/ads/googleads/v15/services/types/conversion_goal_campaign_config_service.py new file mode 100644 index 000000000..2fc43cec5 --- /dev/null +++ b/google/ads/googleads/v15/services/types/conversion_goal_campaign_config_service.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateConversionGoalCampaignConfigsRequest", + "ConversionGoalCampaignConfigOperation", + "MutateConversionGoalCampaignConfigsResponse", + "MutateConversionGoalCampaignConfigResult", + }, +) + + +class MutateConversionGoalCampaignConfigsRequest(proto.Message): + r"""Request message for + [ConversionGoalCampaignConfigService.MutateConversionGoalCampaignConfigs][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/conversion_upload_service.py b/google/ads/googleads/v15/services/types/conversion_upload_service.py new file mode 100644 index 000000000..b70b4b710 --- /dev/null +++ b/google/ads/googleads/v15/services/types/conversion_upload_service.py @@ -0,0 +1,745 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import consent as gagc_consent +from google.ads.googleads.v15.common.types import offline_user_data +from google.ads.googleads.v15.enums.types import conversion_environment_enum +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "UploadClickConversionsRequest", + "UploadClickConversionsResponse", + "UploadCallConversionsRequest", + "UploadCallConversionsResponse", + "ClickConversion", + "CallConversion", + "ExternalAttributionData", + "ClickConversionResult", + "CallConversionResult", + "CustomVariable", + "CartData", + }, +) + + +class UploadClickConversionsRequest(proto.Message): + r"""Request message for + [ConversionUploadService.UploadClickConversions][google.ads.googleads.v15.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.v15.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 + 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. + debug_enabled (bool): + If true, the API will perform all upload checks and return + errors if any are found. If false, it will perform only + basic input validation, skip subsequent upload checks, and + return success even if no click was found for the provided + ``user_identifiers``. + + This setting only affects Enhanced conversions for leads + uploads that use ``user_identifiers`` instead of ``GCLID``, + ``GBRAID``, or ``WBRAID``. When uploading enhanced + conversions for leads, you should upload all conversion + events to the API, including those that may not come from + Google Ads campaigns. The upload of an event that is not + from a Google Ads campaign will result in a + ``CLICK_NOT_FOUND`` error if this field is set to ``true``. + Since these errors are expected for such events, set this + field to ``false`` so you can confirm your uploads are + properly formatted but ignore ``CLICK_NOT_FOUND`` errors + from all of the conversions that are not from a Google Ads + campaign. This will allow you to focus only on errors that + you can address. + + Default is false. + 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, + ) + debug_enabled: bool = proto.Field( + proto.BOOL, + number=5, + ) + job_id: int = proto.Field( + proto.INT32, + number=6, + optional=True, + ) + + +class UploadClickConversionsResponse(proto.Message): + r"""Response message for + [ConversionUploadService.UploadClickConversions][google.ads.googleads.v15.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 + https://developers.google.com/google-ads/api/docs/best-practices/partial-failures + for more information about partial failure. + results (MutableSequence[google.ads.googleads.v15.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.v15.services.ConversionUploadService.UploadCallConversions]. + + Attributes: + customer_id (str): + Required. The ID of the customer performing + the upload. + conversions (MutableSequence[google.ads.googleads.v15.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 + 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. + """ + + 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.v15.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 + https://developers.google.com/google-ads/api/docs/best-practices/partial-failures + for more information about partial failure. + results (MutableSequence[google.ads.googleads.v15.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. + .. _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 click identifier for clicks associated + with app conversions and originating from iOS + devices starting with iOS14. + wbraid (str): + The click identifier for clicks associated + with web conversions and originating from iOS + devices starting with iOS14. + 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.v15.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.v15.services.types.CustomVariable]): + The custom variables associated with this + conversion. + cart_data (google.ads.googleads.v15.services.types.CartData): + The cart data associated with this + conversion. + user_identifiers (MutableSequence[google.ads.googleads.v15.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.v15.enums.types.ConversionEnvironmentEnum.ConversionEnvironment): + The environment this conversion was recorded + on, for example, App or Web. + consent (google.ads.googleads.v15.common.types.Consent): + The consent setting for the event. + """ + + 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, + ) + + +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.v15.services.types.CustomVariable]): + The custom variables associated with this + conversion. + consent (google.ads.googleads.v15.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 click identifier for clicks associated + with app conversions and originating from iOS + devices starting with iOS14. + wbraid (str): + The click identifier for clicks associated + with web conversions and originating from iOS + devices starting with iOS14. + 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.v15.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.v15.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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/conversion_value_rule_service.py b/google/ads/googleads/v15/services/types/conversion_value_rule_service.py new file mode 100644 index 000000000..c410af3c3 --- /dev/null +++ b/google/ads/googleads/v15/services/types/conversion_value_rule_service.py @@ -0,0 +1,207 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateConversionValueRulesRequest", + "ConversionValueRuleOperation", + "MutateConversionValueRulesResponse", + "MutateConversionValueRuleResult", + }, +) + + +class MutateConversionValueRulesRequest(proto.Message): + r"""Request message for + [ConversionValueRuleService.MutateConversionValueRules][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.services.ConversionValueRuleService.MutateConversionValueRules]. + + Attributes: + results (MutableSequence[google.ads.googleads.v15.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.v15.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/v15/services/types/conversion_value_rule_set_service.py b/google/ads/googleads/v15/services/types/conversion_value_rule_set_service.py new file mode 100644 index 000000000..40357bd1d --- /dev/null +++ b/google/ads/googleads/v15/services/types/conversion_value_rule_set_service.py @@ -0,0 +1,205 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateConversionValueRuleSetsRequest", + "ConversionValueRuleSetOperation", + "MutateConversionValueRuleSetsResponse", + "MutateConversionValueRuleSetResult", + }, +) + + +class MutateConversionValueRuleSetsRequest(proto.Message): + r"""Request message for + [ConversionValueRuleSetService.MutateConversionValueRuleSets][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.services.ConversionValueRuleSetService.MutateConversionValueRuleSets]. + + Attributes: + results (MutableSequence[google.ads.googleads.v15.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.v15.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/v15/services/types/custom_audience_service.py b/google/ads/googleads/v15/services/types/custom_audience_service.py new file mode 100644 index 000000000..94e6fa9ed --- /dev/null +++ b/google/ads/googleads/v15/services/types/custom_audience_service.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import custom_audience +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomAudiencesRequest", + "CustomAudienceOperation", + "MutateCustomAudiencesResponse", + "MutateCustomAudienceResult", + }, +) + + +class MutateCustomAudiencesRequest(proto.Message): + r"""Request message for + [CustomAudienceService.MutateCustomAudiences][google.ads.googleads.v15.services.CustomAudienceService.MutateCustomAudiences]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose custom + audiences are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/custom_conversion_goal_service.py b/google/ads/googleads/v15/services/types/custom_conversion_goal_service.py new file mode 100644 index 000000000..0dfe07894 --- /dev/null +++ b/google/ads/googleads/v15/services/types/custom_conversion_goal_service.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomConversionGoalsRequest", + "CustomConversionGoalOperation", + "MutateCustomConversionGoalsResponse", + "MutateCustomConversionGoalResult", + }, +) + + +class MutateCustomConversionGoalsRequest(proto.Message): + r"""Request message for + [CustomConversionGoalService.MutateCustomConversionGoals][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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}/conversionActions/{ConversionGoal.custom_goal_config.conversion_type_ids}' + + 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.v15.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.v15.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/v15/services/types/custom_interest_service.py b/google/ads/googleads/v15/services/types/custom_interest_service.py new file mode 100644 index 000000000..1df47f8eb --- /dev/null +++ b/google/ads/googleads/v15/services/types/custom_interest_service.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import custom_interest +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomInterestsRequest", + "CustomInterestOperation", + "MutateCustomInterestsResponse", + "MutateCustomInterestResult", + }, +) + + +class MutateCustomInterestsRequest(proto.Message): + r"""Request message for + [CustomInterestService.MutateCustomInterests][google.ads.googleads.v15.services.CustomInterestService.MutateCustomInterests]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose custom + interests are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/customer_asset_service.py b/google/ads/googleads/v15/services/types/customer_asset_service.py new file mode 100644 index 000000000..7b69f141b --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_asset_service.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomerAssetsRequest", + "CustomerAssetOperation", + "MutateCustomerAssetsResponse", + "MutateCustomerAssetResult", + }, +) + + +class MutateCustomerAssetsRequest(proto.Message): + r"""Request message for + [CustomerAssetService.MutateCustomerAssets][google.ads.googleads.v15.services.CustomerAssetService.MutateCustomerAssets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + customer assets are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/customer_asset_set_service.py b/google/ads/googleads/v15/services/types/customer_asset_set_service.py new file mode 100644 index 000000000..1f395fdff --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_asset_set_service.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomerAssetSetsRequest", + "CustomerAssetSetOperation", + "MutateCustomerAssetSetsResponse", + "MutateCustomerAssetSetResult", + }, +) + + +class MutateCustomerAssetSetsRequest(proto.Message): + r"""Request message for + [CustomerAssetSetService.MutateCustomerAssetSets][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/customer_client_link_service.py b/google/ads/googleads/v15/services/types/customer_client_link_service.py new file mode 100644 index 000000000..b58ad54b6 --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_client_link_service.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.resources.types import customer_client_link +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomerClientLinkRequest", + "CustomerClientLinkOperation", + "MutateCustomerClientLinkResponse", + "MutateCustomerClientLinkResult", + }, +) + + +class MutateCustomerClientLinkRequest(proto.Message): + r"""Request message for + [CustomerClientLinkService.MutateCustomerClientLink][google.ads.googleads.v15.services.CustomerClientLinkService.MutateCustomerClientLink]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + customer link are being modified. + operation (google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/customer_conversion_goal_service.py b/google/ads/googleads/v15/services/types/customer_conversion_goal_service.py new file mode 100644 index 000000000..09b9f2c79 --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_conversion_goal_service.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import customer_conversion_goal +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomerConversionGoalsRequest", + "CustomerConversionGoalOperation", + "MutateCustomerConversionGoalsResponse", + "MutateCustomerConversionGoalResult", + }, +) + + +class MutateCustomerConversionGoalsRequest(proto.Message): + r"""Request message for + [CustomerConversionGoalService.MutateCustomerConversionGoals][google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/customer_customizer_service.py b/google/ads/googleads/v15/services/types/customer_customizer_service.py new file mode 100644 index 000000000..12fcd6f2a --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_customizer_service.py @@ -0,0 +1,184 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import ( + customer_customizer as gagr_customer_customizer, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomerCustomizersRequest", + "CustomerCustomizerOperation", + "MutateCustomerCustomizersResponse", + "MutateCustomerCustomizerResult", + }, +) + + +class MutateCustomerCustomizersRequest(proto.Message): + r"""Request message for + [CustomerCustomizerService.MutateCustomerCustomizers][google.ads.googleads.v15.services.CustomerCustomizerService.MutateCustomerCustomizers]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + customer customizers are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/customer_extension_setting_service.py b/google/ads/googleads/v15/services/types/customer_extension_setting_service.py new file mode 100644 index 000000000..42f4af540 --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_extension_setting_service.py @@ -0,0 +1,208 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import ( + customer_extension_setting as gagr_customer_extension_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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomerExtensionSettingsRequest", + "CustomerExtensionSettingOperation", + "MutateCustomerExtensionSettingsResponse", + "MutateCustomerExtensionSettingResult", + }, +) + + +class MutateCustomerExtensionSettingsRequest(proto.Message): + r"""Request message for + [CustomerExtensionSettingService.MutateCustomerExtensionSettings][google.ads.googleads.v15.services.CustomerExtensionSettingService.MutateCustomerExtensionSettings]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + customer extension settings are being modified. + operations (MutableSequence[google.ads.googleads.v15.services.types.CustomerExtensionSettingOperation]): + Required. The list of operations to perform + on individual customer extension 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.v15.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[ + "CustomerExtensionSettingOperation" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomerExtensionSettingOperation", + ) + 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 CustomerExtensionSettingOperation(proto.Message): + r"""A single operation (create, update, remove) on a customer + extension setting. + + 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.v15.resources.types.CustomerExtensionSetting): + Create operation: No resource name is + expected for the new customer extension setting. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v15.resources.types.CustomerExtensionSetting): + Update operation: The customer extension + setting 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 + extension setting is expected, in this format: + + ``customers/{customer_id}/customerExtensionSettings/{extension_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_extension_setting.CustomerExtensionSetting = ( + proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_customer_extension_setting.CustomerExtensionSetting, + ) + ) + update: gagr_customer_extension_setting.CustomerExtensionSetting = ( + proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_customer_extension_setting.CustomerExtensionSetting, + ) + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateCustomerExtensionSettingsResponse(proto.Message): + r"""Response message for a customer extension setting 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.v15.services.types.MutateCustomerExtensionSettingResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence[ + "MutateCustomerExtensionSettingResult" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCustomerExtensionSettingResult", + ) + + +class MutateCustomerExtensionSettingResult(proto.Message): + r"""The result for the customer extension setting mutate. + Attributes: + resource_name (str): + Returned for successful operations. + customer_extension_setting (google.ads.googleads.v15.resources.types.CustomerExtensionSetting): + The mutated CustomerExtensionSetting 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_extension_setting: gagr_customer_extension_setting.CustomerExtensionSetting = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_customer_extension_setting.CustomerExtensionSetting, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/customer_feed_service.py b/google/ads/googleads/v15/services/types/customer_feed_service.py new file mode 100644 index 000000000..03809d6c6 --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_feed_service.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import ( + customer_feed as gagr_customer_feed, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomerFeedsRequest", + "CustomerFeedOperation", + "MutateCustomerFeedsResponse", + "MutateCustomerFeedResult", + }, +) + + +class MutateCustomerFeedsRequest(proto.Message): + r"""Request message for + [CustomerFeedService.MutateCustomerFeeds][google.ads.googleads.v15.services.CustomerFeedService.MutateCustomerFeeds]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + customer feeds are being modified. + operations (MutableSequence[google.ads.googleads.v15.services.types.CustomerFeedOperation]): + Required. The list of operations to perform + on individual customer feeds. + 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.v15.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["CustomerFeedOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CustomerFeedOperation", + ) + 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 CustomerFeedOperation(proto.Message): + r"""A single operation (create, update, remove) on a customer + feed. + + 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.v15.resources.types.CustomerFeed): + Create operation: No resource name is + expected for the new customer feed. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v15.resources.types.CustomerFeed): + Update operation: The customer feed 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 + feed is expected, in this format: + + ``customers/{customer_id}/customerFeeds/{feed_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_customer_feed.CustomerFeed = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_customer_feed.CustomerFeed, + ) + update: gagr_customer_feed.CustomerFeed = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_customer_feed.CustomerFeed, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateCustomerFeedsResponse(proto.Message): + r"""Response message for a customer feed 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.v15.services.types.MutateCustomerFeedResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateCustomerFeedResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateCustomerFeedResult", + ) + + +class MutateCustomerFeedResult(proto.Message): + r"""The result for the customer feed mutate. + Attributes: + resource_name (str): + Returned for successful operations. + customer_feed (google.ads.googleads.v15.resources.types.CustomerFeed): + The mutated customer feed 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_feed: gagr_customer_feed.CustomerFeed = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_customer_feed.CustomerFeed, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/customer_label_service.py b/google/ads/googleads/v15/services/types/customer_label_service.py new file mode 100644 index 000000000..3214bd09f --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_label_service.py @@ -0,0 +1,157 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import customer_label +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomerLabelsRequest", + "CustomerLabelOperation", + "MutateCustomerLabelsResponse", + "MutateCustomerLabelResult", + }, +) + + +class MutateCustomerLabelsRequest(proto.Message): + r"""Request message for + [CustomerLabelService.MutateCustomerLabels][google.ads.googleads.v15.services.CustomerLabelService.MutateCustomerLabels]. + + Attributes: + customer_id (str): + Required. ID of the customer whose + customer-label relationships are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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/v15/services/types/customer_lifecycle_goal_service.py b/google/ads/googleads/v15/services/types/customer_lifecycle_goal_service.py new file mode 100644 index 000000000..75df243de --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_lifecycle_goal_service.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.resources.types import customer_lifecycle_goal +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "ConfigureCustomerLifecycleGoalsRequest", + "CustomerLifecycleGoalOperation", + "ConfigureCustomerLifecycleGoalsResponse", + "ConfigureCustomerLifecycleGoalsResult", + }, +) + + +class ConfigureCustomerLifecycleGoalsRequest(proto.Message): + r"""Request message for + [CustomerLifecycleService.configureCustomerLifecycleGoals][]. + + Attributes: + customer_id (str): + Required. The ID of the customer performing + the upload. + operation (google.ads.googleads.v15.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. + .. _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.v15.resources.types.CustomerLifecycleGoal): + Create operation: to create a new customer + lifecycle goal or update an existing customer + lifecycle goal. When creating a new customer + lifecycle goal, all required fields needs to be + set. Resource name and field mask needs to be + empty. When updating an existing customer + lifecycle goal, resource name and field mask + need to be set. Partial update based on field + mask is supported when updating 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, + ) + + +class ConfigureCustomerLifecycleGoalsResponse(proto.Message): + r"""Response message for + [CustomerLifecycleService.configureCustomerLifecycleGoals][]. + + Attributes: + result (google.ads.googleads.v15.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/v15/services/types/customer_manager_link_service.py b/google/ads/googleads/v15/services/types/customer_manager_link_service.py new file mode 100644 index 000000000..32be09e53 --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_manager_link_service.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import customer_manager_link +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomerManagerLinkRequest", + "MoveManagerLinkRequest", + "CustomerManagerLinkOperation", + "MutateCustomerManagerLinkResponse", + "MoveManagerLinkResponse", + "MutateCustomerManagerLinkResult", + }, +) + + +class MutateCustomerManagerLinkRequest(proto.Message): + r"""Request message for + [CustomerManagerLinkService.MutateCustomerManagerLink][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/customer_negative_criterion_service.py b/google/ads/googleads/v15/services/types/customer_negative_criterion_service.py new file mode 100644 index 000000000..bcb0a84f1 --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_negative_criterion_service.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomerNegativeCriteriaRequest", + "CustomerNegativeCriterionOperation", + "MutateCustomerNegativeCriteriaResponse", + "MutateCustomerNegativeCriteriaResult", + }, +) + + +class MutateCustomerNegativeCriteriaRequest(proto.Message): + r"""Request message for + [CustomerNegativeCriterionService.MutateCustomerNegativeCriteria][google.ads.googleads.v15.services.CustomerNegativeCriterionService.MutateCustomerNegativeCriteria]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + criteria are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/customer_service.py b/google/ads/googleads/v15/services/types/customer_service.py new file mode 100644 index 000000000..865ec9224 --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_service.py @@ -0,0 +1,244 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import access_role as gage_access_role +from google.ads.googleads.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import customer as gagr_customer +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomerRequest", + "CreateCustomerClientRequest", + "CustomerOperation", + "CreateCustomerClientResponse", + "MutateCustomerResponse", + "MutateCustomerResult", + "ListAccessibleCustomersRequest", + "ListAccessibleCustomersResponse", + }, +) + + +class MutateCustomerRequest(proto.Message): + r"""Request message for + [CustomerService.MutateCustomer][google.ads.googleads.v15.services.CustomerService.MutateCustomer]. + + Attributes: + customer_id (str): + Required. The ID of the customer being + modified. + operation (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.services.CustomerService.ListAccessibleCustomers]. + + """ + + +class ListAccessibleCustomersResponse(proto.Message): + r"""Response message for + [CustomerService.ListAccessibleCustomers][google.ads.googleads.v15.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/v15/services/types/customer_sk_ad_network_conversion_value_schema_service.py b/google/ads/googleads/v15/services/types/customer_sk_ad_network_conversion_value_schema_service.py new file mode 100644 index 000000000..afea8d347 --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_sk_ad_network_conversion_value_schema_service.py @@ -0,0 +1,127 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.resources.types import ( + customer_sk_ad_network_conversion_value_schema, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "CustomerSkAdNetworkConversionValueSchemaOperation", + "MutateCustomerSkAdNetworkConversionValueSchemaRequest", + "MutateCustomerSkAdNetworkConversionValueSchemaResult", + "MutateCustomerSkAdNetworkConversionValueSchemaResponse", + }, +) + + +class CustomerSkAdNetworkConversionValueSchemaOperation(proto.Message): + r"""A single update operation for a + CustomerSkAdNetworkConversionValueSchema. + + Attributes: + update (google.ads.googleads.v15.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.v15.services.CustomerSkAdNetworkConversionValueSchemaService.MutateCustomerSkAdNetworkConversionValueSchema]. + + Attributes: + customer_id (str): + The ID of the customer whose shared sets are + being modified. + operation (google.ads.googleads.v15.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. + """ + + 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, + ) + + +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.v15.services.types.MutateCustomerSkAdNetworkConversionValueSchemaResult): + All results for the mutate. + """ + + result: "MutateCustomerSkAdNetworkConversionValueSchemaResult" = ( + proto.Field( + proto.MESSAGE, + number=1, + message="MutateCustomerSkAdNetworkConversionValueSchemaResult", + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/customer_user_access_invitation_service.py b/google/ads/googleads/v15/services/types/customer_user_access_invitation_service.py new file mode 100644 index 000000000..9f38f4883 --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_user_access_invitation_service.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.resources.types import ( + customer_user_access_invitation, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomerUserAccessInvitationRequest", + "CustomerUserAccessInvitationOperation", + "MutateCustomerUserAccessInvitationResponse", + "MutateCustomerUserAccessInvitationResult", + }, +) + + +class MutateCustomerUserAccessInvitationRequest(proto.Message): + r"""Request message for + [CustomerUserAccessInvitationService.MutateCustomerUserAccessInvitation][google.ads.googleads.v15.services.CustomerUserAccessInvitationService.MutateCustomerUserAccessInvitation] + + Attributes: + customer_id (str): + Required. The ID of the customer whose access + invitation is being modified. + operation (google.ads.googleads.v15.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.v15.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.v15.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/v15/services/types/customer_user_access_service.py b/google/ads/googleads/v15/services/types/customer_user_access_service.py new file mode 100644 index 000000000..47a75f8fc --- /dev/null +++ b/google/ads/googleads/v15/services/types/customer_user_access_service.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.resources.types import customer_user_access +from google.protobuf import field_mask_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomerUserAccessRequest", + "CustomerUserAccessOperation", + "MutateCustomerUserAccessResponse", + "MutateCustomerUserAccessResult", + }, +) + + +class MutateCustomerUserAccessRequest(proto.Message): + r"""Mutate Request for + [CustomerUserAccessService.MutateCustomerUserAccess][google.ads.googleads.v15.services.CustomerUserAccessService.MutateCustomerUserAccess]. + + Attributes: + customer_id (str): + Required. The ID of the customer being + modified. + operation (google.ads.googleads.v15.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.v15.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.v15.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/v15/services/types/customizer_attribute_service.py b/google/ads/googleads/v15/services/types/customizer_attribute_service.py new file mode 100644 index 000000000..9cfd7ebc0 --- /dev/null +++ b/google/ads/googleads/v15/services/types/customizer_attribute_service.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateCustomizerAttributesRequest", + "CustomizerAttributeOperation", + "MutateCustomizerAttributesResponse", + "MutateCustomizerAttributeResult", + }, +) + + +class MutateCustomizerAttributesRequest(proto.Message): + r"""Request message for + [CustomizerAttributeService.MutateCustomizerAttributes][google.ads.googleads.v15.services.CustomizerAttributeService.MutateCustomizerAttributes]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + customizer attributes are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/experiment_arm_service.py b/google/ads/googleads/v15/services/types/experiment_arm_service.py new file mode 100644 index 000000000..4f58c080c --- /dev/null +++ b/google/ads/googleads/v15/services/types/experiment_arm_service.py @@ -0,0 +1,196 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateExperimentArmsRequest", + "ExperimentArmOperation", + "MutateExperimentArmsResponse", + "MutateExperimentArmResult", + }, +) + + +class MutateExperimentArmsRequest(proto.Message): + r"""Request message for + [ExperimentArmService.MutateExperimentArms][google.ads.googleads.v15.services.ExperimentArmService.MutateExperimentArms]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + experiments are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.resources.types.ExperimentArm): + Create operation + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v15.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.v15.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.v15.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/v15/services/types/experiment_service.py b/google/ads/googleads/v15/services/types/experiment_service.py new file mode 100644 index 000000000..4a254c21f --- /dev/null +++ b/google/ads/googleads/v15/services/types/experiment_service.py @@ -0,0 +1,401 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.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.v15.services", + marshal="google.ads.googleads.v15", + 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.v15.services.ExperimentService.MutateExperiments]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + experiments are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.resources.types.Experiment): + Create operation + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.services.ExperimentService.GraduateExperiment]. + + Attributes: + experiment (str): + Required. The experiment to be graduated. + campaign_budget_mappings (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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/v15/services/types/extension_feed_item_service.py b/google/ads/googleads/v15/services/types/extension_feed_item_service.py new file mode 100644 index 000000000..2ba6a1d91 --- /dev/null +++ b/google/ads/googleads/v15/services/types/extension_feed_item_service.py @@ -0,0 +1,205 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import ( + extension_feed_item as gagr_extension_feed_item, +) +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateExtensionFeedItemsRequest", + "ExtensionFeedItemOperation", + "MutateExtensionFeedItemsResponse", + "MutateExtensionFeedItemResult", + }, +) + + +class MutateExtensionFeedItemsRequest(proto.Message): + r"""Request message for + [ExtensionFeedItemService.MutateExtensionFeedItems][google.ads.googleads.v15.services.ExtensionFeedItemService.MutateExtensionFeedItems]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + extension feed items are being modified. + operations (MutableSequence[google.ads.googleads.v15.services.types.ExtensionFeedItemOperation]): + Required. The list of operations to perform + on individual extension feed items. + 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.v15.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[ + "ExtensionFeedItemOperation" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ExtensionFeedItemOperation", + ) + 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 ExtensionFeedItemOperation(proto.Message): + r"""A single operation (create, update, remove) on an extension + feed 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v15.resources.types.ExtensionFeedItem): + Create operation: No resource name is + expected for the new extension feed item. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v15.resources.types.ExtensionFeedItem): + Update operation: The extension feed item 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 extension + feed item is expected, in this format: + + ``customers/{customer_id}/extensionFeedItems/{feed_item_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_extension_feed_item.ExtensionFeedItem = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_extension_feed_item.ExtensionFeedItem, + ) + update: gagr_extension_feed_item.ExtensionFeedItem = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_extension_feed_item.ExtensionFeedItem, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateExtensionFeedItemsResponse(proto.Message): + r"""Response message for an extension feed item 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.v15.services.types.MutateExtensionFeedItemResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence[ + "MutateExtensionFeedItemResult" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateExtensionFeedItemResult", + ) + + +class MutateExtensionFeedItemResult(proto.Message): + r"""The result for the extension feed item mutate. + Attributes: + resource_name (str): + Returned for successful operations. + extension_feed_item (google.ads.googleads.v15.resources.types.ExtensionFeedItem): + The mutated extension feed item 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, + ) + extension_feed_item: gagr_extension_feed_item.ExtensionFeedItem = ( + proto.Field( + proto.MESSAGE, + number=2, + message=gagr_extension_feed_item.ExtensionFeedItem, + ) + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/feed_item_service.py b/google/ads/googleads/v15/services/types/feed_item_service.py new file mode 100644 index 000000000..8e654fda2 --- /dev/null +++ b/google/ads/googleads/v15/services/types/feed_item_service.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import feed_item as gagr_feed_item +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateFeedItemsRequest", + "FeedItemOperation", + "MutateFeedItemsResponse", + "MutateFeedItemResult", + }, +) + + +class MutateFeedItemsRequest(proto.Message): + r"""Request message for + [FeedItemService.MutateFeedItems][google.ads.googleads.v15.services.FeedItemService.MutateFeedItems]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose feed + items are being modified. + operations (MutableSequence[google.ads.googleads.v15.services.types.FeedItemOperation]): + Required. The list of operations to perform + on individual feed items. + 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.v15.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["FeedItemOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="FeedItemOperation", + ) + 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 FeedItemOperation(proto.Message): + r"""A single operation (create, update, remove) on an feed 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: + update_mask (google.protobuf.field_mask_pb2.FieldMask): + FieldMask that determines which resource + fields are modified in an update. + create (google.ads.googleads.v15.resources.types.FeedItem): + Create operation: No resource name is + expected for the new feed item. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v15.resources.types.FeedItem): + Update operation: The feed item 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 feed item + is expected, in this format: + + ``customers/{customer_id}/feedItems/{feed_id}~{feed_item_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_feed_item.FeedItem = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_feed_item.FeedItem, + ) + update: gagr_feed_item.FeedItem = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_feed_item.FeedItem, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateFeedItemsResponse(proto.Message): + r"""Response message for an feed item 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.v15.services.types.MutateFeedItemResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateFeedItemResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateFeedItemResult", + ) + + +class MutateFeedItemResult(proto.Message): + r"""The result for the feed item mutate. + Attributes: + resource_name (str): + Returned for successful operations. + feed_item (google.ads.googleads.v15.resources.types.FeedItem): + The mutated feed item 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, + ) + feed_item: gagr_feed_item.FeedItem = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_feed_item.FeedItem, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/feed_item_set_link_service.py b/google/ads/googleads/v15/services/types/feed_item_set_link_service.py new file mode 100644 index 000000000..a5cc89d7b --- /dev/null +++ b/google/ads/googleads/v15/services/types/feed_item_set_link_service.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import feed_item_set_link +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateFeedItemSetLinksRequest", + "FeedItemSetLinkOperation", + "MutateFeedItemSetLinksResponse", + "MutateFeedItemSetLinkResult", + }, +) + + +class MutateFeedItemSetLinksRequest(proto.Message): + r"""Request message for + [FeedItemSetLinkService.MutateFeedItemSetLinks][google.ads.googleads.v15.services.FeedItemSetLinkService.MutateFeedItemSetLinks]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose feed + item set links are being modified. + operations (MutableSequence[google.ads.googleads.v15.services.types.FeedItemSetLinkOperation]): + Required. The list of operations to perform + on individual feed item set links. + 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[ + "FeedItemSetLinkOperation" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="FeedItemSetLinkOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class FeedItemSetLinkOperation(proto.Message): + r"""A single operation (create, update, remove) on a feed item + set 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: + create (google.ads.googleads.v15.resources.types.FeedItemSetLink): + Create operation: No resource name is + expected for the new feed item set link. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed feed item + set link is expected, in this format: + + ``customers/{customer_id}/feedItemSetLinks/{feed_id}_{feed_item_set_id}_{feed_item_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: feed_item_set_link.FeedItemSetLink = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=feed_item_set_link.FeedItemSetLink, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateFeedItemSetLinksResponse(proto.Message): + r"""Response message for a feed item set link mutate. + Attributes: + results (MutableSequence[google.ads.googleads.v15.services.types.MutateFeedItemSetLinkResult]): + 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[ + "MutateFeedItemSetLinkResult" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateFeedItemSetLinkResult", + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateFeedItemSetLinkResult(proto.Message): + r"""The result for the feed item set 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/v15/services/types/feed_item_set_service.py b/google/ads/googleads/v15/services/types/feed_item_set_service.py new file mode 100644 index 000000000..47edf779f --- /dev/null +++ b/google/ads/googleads/v15/services/types/feed_item_set_service.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import feed_item_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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateFeedItemSetsRequest", + "FeedItemSetOperation", + "MutateFeedItemSetsResponse", + "MutateFeedItemSetResult", + }, +) + + +class MutateFeedItemSetsRequest(proto.Message): + r"""Request message for + [FeedItemSetService.MutateFeedItemSets][google.ads.googleads.v15.services.FeedItemSetService.MutateFeedItemSets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose feed + item sets are being modified. + operations (MutableSequence[google.ads.googleads.v15.services.types.FeedItemSetOperation]): + Required. The list of operations to perform + on individual feed item 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. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operations: MutableSequence["FeedItemSetOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="FeedItemSetOperation", + ) + partial_failure: bool = proto.Field( + proto.BOOL, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +class FeedItemSetOperation(proto.Message): + r"""A single operation (create, remove) on an feed item 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.v15.resources.types.FeedItemSet): + Create operation: No resource name is + expected for the new feed item set + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v15.resources.types.FeedItemSet): + Update operation: The feed item 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 feed item + is expected, in this format: + ``customers/{customer_id}/feedItems/{feed_id}~{feed_item_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: feed_item_set.FeedItemSet = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=feed_item_set.FeedItemSet, + ) + update: feed_item_set.FeedItemSet = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=feed_item_set.FeedItemSet, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateFeedItemSetsResponse(proto.Message): + r"""Response message for an feed item set mutate. + Attributes: + results (MutableSequence[google.ads.googleads.v15.services.types.MutateFeedItemSetResult]): + 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["MutateFeedItemSetResult"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="MutateFeedItemSetResult", + ) + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + + +class MutateFeedItemSetResult(proto.Message): + r"""The result for the feed item set 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/v15/services/types/feed_item_target_service.py b/google/ads/googleads/v15/services/types/feed_item_target_service.py new file mode 100644 index 000000000..102f0354b --- /dev/null +++ b/google/ads/googleads/v15/services/types/feed_item_target_service.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import ( + feed_item_target as gagr_feed_item_target, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateFeedItemTargetsRequest", + "FeedItemTargetOperation", + "MutateFeedItemTargetsResponse", + "MutateFeedItemTargetResult", + }, +) + + +class MutateFeedItemTargetsRequest(proto.Message): + r"""Request message for + [FeedItemTargetService.MutateFeedItemTargets][google.ads.googleads.v15.services.FeedItemTargetService.MutateFeedItemTargets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose feed + item targets are being modified. + operations (MutableSequence[google.ads.googleads.v15.services.types.FeedItemTargetOperation]): + Required. The list of operations to perform + on individual feed item targets. + 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.v15.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[ + "FeedItemTargetOperation" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="FeedItemTargetOperation", + ) + 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 FeedItemTargetOperation(proto.Message): + r"""A single operation (create, remove) on an feed item target. + 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.v15.resources.types.FeedItemTarget): + Create operation: No resource name is + expected for the new feed item target. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed feed item + target is expected, in this format: + + ``customers/{customer_id}/feedItemTargets/{feed_id}~{feed_item_id}~{feed_item_target_type}~{feed_item_target_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: gagr_feed_item_target.FeedItemTarget = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_feed_item_target.FeedItemTarget, + ) + remove: str = proto.Field( + proto.STRING, + number=2, + oneof="operation", + ) + + +class MutateFeedItemTargetsResponse(proto.Message): + r"""Response message for an feed item target 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.v15.services.types.MutateFeedItemTargetResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence[ + "MutateFeedItemTargetResult" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateFeedItemTargetResult", + ) + + +class MutateFeedItemTargetResult(proto.Message): + r"""The result for the feed item target mutate. + Attributes: + resource_name (str): + Returned for successful operations. + feed_item_target (google.ads.googleads.v15.resources.types.FeedItemTarget): + The mutated feed item target 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, + ) + feed_item_target: gagr_feed_item_target.FeedItemTarget = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_feed_item_target.FeedItemTarget, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/feed_mapping_service.py b/google/ads/googleads/v15/services/types/feed_mapping_service.py new file mode 100644 index 000000000..d913ba486 --- /dev/null +++ b/google/ads/googleads/v15/services/types/feed_mapping_service.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import ( + feed_mapping as gagr_feed_mapping, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateFeedMappingsRequest", + "FeedMappingOperation", + "MutateFeedMappingsResponse", + "MutateFeedMappingResult", + }, +) + + +class MutateFeedMappingsRequest(proto.Message): + r"""Request message for + [FeedMappingService.MutateFeedMappings][google.ads.googleads.v15.services.FeedMappingService.MutateFeedMappings]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose feed + mappings are being modified. + operations (MutableSequence[google.ads.googleads.v15.services.types.FeedMappingOperation]): + Required. The list of operations to perform + on individual feed mappings. + 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.v15.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["FeedMappingOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="FeedMappingOperation", + ) + 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 FeedMappingOperation(proto.Message): + r"""A single operation (create, remove) on a feed mapping. + 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.v15.resources.types.FeedMapping): + Create operation: No resource name is + expected for the new feed mapping. + + This field is a member of `oneof`_ ``operation``. + remove (str): + Remove operation: A resource name for the removed feed + mapping is expected, in this format: + + ``customers/{customer_id}/feedMappings/{feed_id}~{feed_mapping_id}`` + + This field is a member of `oneof`_ ``operation``. + """ + + create: gagr_feed_mapping.FeedMapping = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_feed_mapping.FeedMapping, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateFeedMappingsResponse(proto.Message): + r"""Response message for a feed mapping 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.v15.services.types.MutateFeedMappingResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateFeedMappingResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateFeedMappingResult", + ) + + +class MutateFeedMappingResult(proto.Message): + r"""The result for the feed mapping mutate. + Attributes: + resource_name (str): + Returned for successful operations. + feed_mapping (google.ads.googleads.v15.resources.types.FeedMapping): + The mutated feed mapping 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, + ) + feed_mapping: gagr_feed_mapping.FeedMapping = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_feed_mapping.FeedMapping, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/feed_service.py b/google/ads/googleads/v15/services/types/feed_service.py new file mode 100644 index 000000000..91e2e8af8 --- /dev/null +++ b/google/ads/googleads/v15/services/types/feed_service.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import feed as gagr_feed +from google.protobuf import field_mask_pb2 # type: ignore +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateFeedsRequest", + "FeedOperation", + "MutateFeedsResponse", + "MutateFeedResult", + }, +) + + +class MutateFeedsRequest(proto.Message): + r"""Request message for + [FeedService.MutateFeeds][google.ads.googleads.v15.services.FeedService.MutateFeeds]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose feeds + are being modified. + operations (MutableSequence[google.ads.googleads.v15.services.types.FeedOperation]): + Required. The list of operations to perform + on individual feeds. + 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.v15.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["FeedOperation"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="FeedOperation", + ) + 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 FeedOperation(proto.Message): + r"""A single operation (create, update, remove) on an feed. + 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.v15.resources.types.Feed): + Create operation: No resource name is + expected for the new feed. + + This field is a member of `oneof`_ ``operation``. + update (google.ads.googleads.v15.resources.types.Feed): + Update operation: The feed 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 feed is + expected, in this format: + + ``customers/{customer_id}/feeds/{feed_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_feed.Feed = proto.Field( + proto.MESSAGE, + number=1, + oneof="operation", + message=gagr_feed.Feed, + ) + update: gagr_feed.Feed = proto.Field( + proto.MESSAGE, + number=2, + oneof="operation", + message=gagr_feed.Feed, + ) + remove: str = proto.Field( + proto.STRING, + number=3, + oneof="operation", + ) + + +class MutateFeedsResponse(proto.Message): + r"""Response message for an feed 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.v15.services.types.MutateFeedResult]): + All results for the mutate. + """ + + partial_failure_error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=3, + message=status_pb2.Status, + ) + results: MutableSequence["MutateFeedResult"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="MutateFeedResult", + ) + + +class MutateFeedResult(proto.Message): + r"""The result for the feed mutate. + Attributes: + resource_name (str): + Returned for successful operations. + feed (google.ads.googleads.v15.resources.types.Feed): + The mutated feed 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, + ) + feed: gagr_feed.Feed = proto.Field( + proto.MESSAGE, + number=2, + message=gagr_feed.Feed, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/geo_target_constant_service.py b/google/ads/googleads/v15/services/types/geo_target_constant_service.py new file mode 100644 index 000000000..34bb25305 --- /dev/null +++ b/google/ads/googleads/v15/services/types/geo_target_constant_service.py @@ -0,0 +1,204 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import ( + geo_target_constant as gagr_geo_target_constant, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "SuggestGeoTargetConstantsRequest", + "SuggestGeoTargetConstantsResponse", + "GeoTargetConstantSuggestion", + }, +) + + +class SuggestGeoTargetConstantsRequest(proto.Message): + r"""Request message for + [GeoTargetConstantService.SuggestGeoTargetConstants][google.ads.googleads.v15.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.v15.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.v15.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.v15.services.GeoTargetConstantService.SuggestGeoTargetConstants]. + + Attributes: + geo_target_constant_suggestions (MutableSequence[google.ads.googleads.v15.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.v15.resources.types.GeoTargetConstant): + The GeoTargetConstant result. + geo_target_constant_parents (MutableSequence[google.ads.googleads.v15.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/v15/services/types/google_ads_field_service.py b/google/ads/googleads/v15/services/types/google_ads_field_service.py new file mode 100644 index 000000000..93d769009 --- /dev/null +++ b/google/ads/googleads/v15/services/types/google_ads_field_service.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import google_ads_field + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "GetGoogleAdsFieldRequest", + "SearchGoogleAdsFieldsRequest", + "SearchGoogleAdsFieldsResponse", + }, +) + + +class GetGoogleAdsFieldRequest(proto.Message): + r"""Request message for + [GoogleAdsFieldService.GetGoogleAdsField][google.ads.googleads.v15.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.v15.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.v15.services.GoogleAdsFieldService.SearchGoogleAdsFields]. + + Attributes: + results (MutableSequence[google.ads.googleads.v15.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/v15/services/types/google_ads_service.py b/google/ads/googleads/v15/services/types/google_ads_service.py new file mode 100644 index 000000000..466a26fa4 --- /dev/null +++ b/google/ads/googleads/v15/services/types/google_ads_service.py @@ -0,0 +1,3978 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import metrics as gagc_metrics +from google.ads.googleads.v15.common.types import segments as gagc_segments +from google.ads.googleads.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.enums.types import ( + summary_row_setting as gage_summary_row_setting, +) +from google.ads.googleads.v15.resources.types import ( + accessible_bidding_strategy as gagr_accessible_bidding_strategy, +) +from google.ads.googleads.v15.resources.types import ( + account_budget as gagr_account_budget, +) +from google.ads.googleads.v15.resources.types import ( + account_budget_proposal as gagr_account_budget_proposal, +) +from google.ads.googleads.v15.resources.types import ( + account_link as gagr_account_link, +) +from google.ads.googleads.v15.resources.types import ad_group as gagr_ad_group +from google.ads.googleads.v15.resources.types import ( + ad_group_ad as gagr_ad_group_ad, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_ad_asset_combination_view as gagr_ad_group_ad_asset_combination_view, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_ad_asset_view as gagr_ad_group_ad_asset_view, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_ad_label as gagr_ad_group_ad_label, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_asset as gagr_ad_group_asset, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_asset_set as gagr_ad_group_asset_set, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_audience_view as gagr_ad_group_audience_view, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_bid_modifier as gagr_ad_group_bid_modifier, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_criterion as gagr_ad_group_criterion, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_criterion_customizer as gagr_ad_group_criterion_customizer, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_criterion_label as gagr_ad_group_criterion_label, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_criterion_simulation as gagr_ad_group_criterion_simulation, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_customizer as gagr_ad_group_customizer, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_extension_setting as gagr_ad_group_extension_setting, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_feed as gagr_ad_group_feed, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_label as gagr_ad_group_label, +) +from google.ads.googleads.v15.resources.types import ( + ad_group_simulation as gagr_ad_group_simulation, +) +from google.ads.googleads.v15.resources.types import ( + ad_parameter as gagr_ad_parameter, +) +from google.ads.googleads.v15.resources.types import ( + ad_schedule_view as gagr_ad_schedule_view, +) +from google.ads.googleads.v15.resources.types import ( + age_range_view as gagr_age_range_view, +) +from google.ads.googleads.v15.resources.types import ( + android_privacy_shared_key_google_ad_group as gagr_android_privacy_shared_key_google_ad_group, +) +from google.ads.googleads.v15.resources.types import ( + android_privacy_shared_key_google_campaign as gagr_android_privacy_shared_key_google_campaign, +) +from google.ads.googleads.v15.resources.types import ( + android_privacy_shared_key_google_network_type as gagr_android_privacy_shared_key_google_network_type, +) +from google.ads.googleads.v15.resources.types import asset as gagr_asset +from google.ads.googleads.v15.resources.types import ( + asset_field_type_view as gagr_asset_field_type_view, +) +from google.ads.googleads.v15.resources.types import ( + asset_group as gagr_asset_group, +) +from google.ads.googleads.v15.resources.types import ( + asset_group_asset as gagr_asset_group_asset, +) +from google.ads.googleads.v15.resources.types import ( + asset_group_listing_group_filter as gagr_asset_group_listing_group_filter, +) +from google.ads.googleads.v15.resources.types import ( + asset_group_product_group_view as gagr_asset_group_product_group_view, +) +from google.ads.googleads.v15.resources.types import ( + asset_group_signal as gagr_asset_group_signal, +) +from google.ads.googleads.v15.resources.types import ( + asset_group_top_combination_view as gagr_asset_group_top_combination_view, +) +from google.ads.googleads.v15.resources.types import asset_set as gagr_asset_set +from google.ads.googleads.v15.resources.types import ( + asset_set_asset as gagr_asset_set_asset, +) +from google.ads.googleads.v15.resources.types import ( + asset_set_type_view as gagr_asset_set_type_view, +) +from google.ads.googleads.v15.resources.types import audience as gagr_audience +from google.ads.googleads.v15.resources.types import batch_job as gagr_batch_job +from google.ads.googleads.v15.resources.types import ( + bidding_data_exclusion as gagr_bidding_data_exclusion, +) +from google.ads.googleads.v15.resources.types import ( + bidding_seasonality_adjustment as gagr_bidding_seasonality_adjustment, +) +from google.ads.googleads.v15.resources.types import ( + bidding_strategy as gagr_bidding_strategy, +) +from google.ads.googleads.v15.resources.types import ( + bidding_strategy_simulation as gagr_bidding_strategy_simulation, +) +from google.ads.googleads.v15.resources.types import ( + billing_setup as gagr_billing_setup, +) +from google.ads.googleads.v15.resources.types import call_view as gagr_call_view +from google.ads.googleads.v15.resources.types import campaign as gagr_campaign +from google.ads.googleads.v15.resources.types import ( + campaign_asset as gagr_campaign_asset, +) +from google.ads.googleads.v15.resources.types import ( + campaign_asset_set as gagr_campaign_asset_set, +) +from google.ads.googleads.v15.resources.types import ( + campaign_audience_view as gagr_campaign_audience_view, +) +from google.ads.googleads.v15.resources.types import ( + campaign_bid_modifier as gagr_campaign_bid_modifier, +) +from google.ads.googleads.v15.resources.types import ( + campaign_budget as gagr_campaign_budget, +) +from google.ads.googleads.v15.resources.types import ( + campaign_conversion_goal as gagr_campaign_conversion_goal, +) +from google.ads.googleads.v15.resources.types import ( + campaign_criterion as gagr_campaign_criterion, +) +from google.ads.googleads.v15.resources.types import ( + campaign_customizer as gagr_campaign_customizer, +) +from google.ads.googleads.v15.resources.types import ( + campaign_draft as gagr_campaign_draft, +) +from google.ads.googleads.v15.resources.types import ( + campaign_extension_setting as gagr_campaign_extension_setting, +) +from google.ads.googleads.v15.resources.types import ( + campaign_feed as gagr_campaign_feed, +) +from google.ads.googleads.v15.resources.types import ( + campaign_group as gagr_campaign_group, +) +from google.ads.googleads.v15.resources.types import ( + campaign_label as gagr_campaign_label, +) +from google.ads.googleads.v15.resources.types import ( + campaign_lifecycle_goal as gagr_campaign_lifecycle_goal, +) +from google.ads.googleads.v15.resources.types import ( + campaign_search_term_insight as gagr_campaign_search_term_insight, +) +from google.ads.googleads.v15.resources.types import ( + campaign_shared_set as gagr_campaign_shared_set, +) +from google.ads.googleads.v15.resources.types import ( + campaign_simulation as gagr_campaign_simulation, +) +from google.ads.googleads.v15.resources.types import ( + carrier_constant as gagr_carrier_constant, +) +from google.ads.googleads.v15.resources.types import ( + change_event as gagr_change_event, +) +from google.ads.googleads.v15.resources.types import ( + change_status as gagr_change_status, +) +from google.ads.googleads.v15.resources.types import ( + click_view as gagr_click_view, +) +from google.ads.googleads.v15.resources.types import ( + combined_audience as gagr_combined_audience, +) +from google.ads.googleads.v15.resources.types import ( + conversion_action as gagr_conversion_action, +) +from google.ads.googleads.v15.resources.types import ( + conversion_custom_variable as gagr_conversion_custom_variable, +) +from google.ads.googleads.v15.resources.types import ( + conversion_goal_campaign_config as gagr_conversion_goal_campaign_config, +) +from google.ads.googleads.v15.resources.types import ( + conversion_value_rule as gagr_conversion_value_rule, +) +from google.ads.googleads.v15.resources.types import ( + conversion_value_rule_set as gagr_conversion_value_rule_set, +) +from google.ads.googleads.v15.resources.types import ( + currency_constant as gagr_currency_constant, +) +from google.ads.googleads.v15.resources.types import ( + custom_audience as gagr_custom_audience, +) +from google.ads.googleads.v15.resources.types import ( + custom_conversion_goal as gagr_custom_conversion_goal, +) +from google.ads.googleads.v15.resources.types import ( + custom_interest as gagr_custom_interest, +) +from google.ads.googleads.v15.resources.types import customer as gagr_customer +from google.ads.googleads.v15.resources.types import ( + customer_asset as gagr_customer_asset, +) +from google.ads.googleads.v15.resources.types import ( + customer_asset_set as gagr_customer_asset_set, +) +from google.ads.googleads.v15.resources.types import ( + customer_client as gagr_customer_client, +) +from google.ads.googleads.v15.resources.types import ( + customer_client_link as gagr_customer_client_link, +) +from google.ads.googleads.v15.resources.types import ( + customer_conversion_goal as gagr_customer_conversion_goal, +) +from google.ads.googleads.v15.resources.types import ( + customer_customizer as gagr_customer_customizer, +) +from google.ads.googleads.v15.resources.types import ( + customer_extension_setting as gagr_customer_extension_setting, +) +from google.ads.googleads.v15.resources.types import ( + customer_feed as gagr_customer_feed, +) +from google.ads.googleads.v15.resources.types import ( + customer_label as gagr_customer_label, +) +from google.ads.googleads.v15.resources.types import ( + customer_lifecycle_goal as gagr_customer_lifecycle_goal, +) +from google.ads.googleads.v15.resources.types import ( + customer_manager_link as gagr_customer_manager_link, +) +from google.ads.googleads.v15.resources.types import ( + customer_negative_criterion as gagr_customer_negative_criterion, +) +from google.ads.googleads.v15.resources.types import ( + customer_search_term_insight as gagr_customer_search_term_insight, +) +from google.ads.googleads.v15.resources.types import ( + customer_user_access as gagr_customer_user_access, +) +from google.ads.googleads.v15.resources.types import ( + customer_user_access_invitation as gagr_customer_user_access_invitation, +) +from google.ads.googleads.v15.resources.types import ( + customizer_attribute as gagr_customizer_attribute, +) +from google.ads.googleads.v15.resources.types import ( + detail_placement_view as gagr_detail_placement_view, +) +from google.ads.googleads.v15.resources.types import ( + detailed_demographic as gagr_detailed_demographic, +) +from google.ads.googleads.v15.resources.types import ( + display_keyword_view as gagr_display_keyword_view, +) +from google.ads.googleads.v15.resources.types import ( + distance_view as gagr_distance_view, +) +from google.ads.googleads.v15.resources.types import ( + domain_category as gagr_domain_category, +) +from google.ads.googleads.v15.resources.types import ( + dynamic_search_ads_search_term_view as gagr_dynamic_search_ads_search_term_view, +) +from google.ads.googleads.v15.resources.types import ( + expanded_landing_page_view as gagr_expanded_landing_page_view, +) +from google.ads.googleads.v15.resources.types import ( + experiment as gagr_experiment, +) +from google.ads.googleads.v15.resources.types import ( + experiment_arm as gagr_experiment_arm, +) +from google.ads.googleads.v15.resources.types import ( + extension_feed_item as gagr_extension_feed_item, +) +from google.ads.googleads.v15.resources.types import feed as gagr_feed +from google.ads.googleads.v15.resources.types import feed_item as gagr_feed_item +from google.ads.googleads.v15.resources.types import ( + feed_item_set as gagr_feed_item_set, +) +from google.ads.googleads.v15.resources.types import ( + feed_item_set_link as gagr_feed_item_set_link, +) +from google.ads.googleads.v15.resources.types import ( + feed_item_target as gagr_feed_item_target, +) +from google.ads.googleads.v15.resources.types import ( + feed_mapping as gagr_feed_mapping, +) +from google.ads.googleads.v15.resources.types import ( + feed_placeholder_view as gagr_feed_placeholder_view, +) +from google.ads.googleads.v15.resources.types import ( + gender_view as gagr_gender_view, +) +from google.ads.googleads.v15.resources.types import ( + geo_target_constant as gagr_geo_target_constant, +) +from google.ads.googleads.v15.resources.types import ( + geographic_view as gagr_geographic_view, +) +from google.ads.googleads.v15.resources.types import ( + group_placement_view as gagr_group_placement_view, +) +from google.ads.googleads.v15.resources.types import ( + hotel_group_view as gagr_hotel_group_view, +) +from google.ads.googleads.v15.resources.types import ( + hotel_performance_view as gagr_hotel_performance_view, +) +from google.ads.googleads.v15.resources.types import ( + hotel_reconciliation as gagr_hotel_reconciliation, +) +from google.ads.googleads.v15.resources.types import ( + income_range_view as gagr_income_range_view, +) +from google.ads.googleads.v15.resources.types import ( + keyword_plan as gagr_keyword_plan, +) +from google.ads.googleads.v15.resources.types import ( + keyword_plan_ad_group as gagr_keyword_plan_ad_group, +) +from google.ads.googleads.v15.resources.types import ( + keyword_plan_ad_group_keyword as gagr_keyword_plan_ad_group_keyword, +) +from google.ads.googleads.v15.resources.types import ( + keyword_plan_campaign as gagr_keyword_plan_campaign, +) +from google.ads.googleads.v15.resources.types import ( + keyword_plan_campaign_keyword as gagr_keyword_plan_campaign_keyword, +) +from google.ads.googleads.v15.resources.types import ( + keyword_theme_constant as gagr_keyword_theme_constant, +) +from google.ads.googleads.v15.resources.types import ( + keyword_view as gagr_keyword_view, +) +from google.ads.googleads.v15.resources.types import label as gagr_label +from google.ads.googleads.v15.resources.types import ( + landing_page_view as gagr_landing_page_view, +) +from google.ads.googleads.v15.resources.types import ( + language_constant as gagr_language_constant, +) +from google.ads.googleads.v15.resources.types import ( + lead_form_submission_data as gagr_lead_form_submission_data, +) +from google.ads.googleads.v15.resources.types import ( + life_event as gagr_life_event, +) +from google.ads.googleads.v15.resources.types import ( + local_services_lead as gagr_local_services_lead, +) +from google.ads.googleads.v15.resources.types import ( + local_services_lead_conversation as gagr_local_services_lead_conversation, +) +from google.ads.googleads.v15.resources.types import ( + local_services_verification_artifact as gagr_local_services_verification_artifact, +) +from google.ads.googleads.v15.resources.types import ( + location_view as gagr_location_view, +) +from google.ads.googleads.v15.resources.types import ( + managed_placement_view as gagr_managed_placement_view, +) +from google.ads.googleads.v15.resources.types import ( + media_file as gagr_media_file, +) +from google.ads.googleads.v15.resources.types import ( + mobile_app_category_constant as gagr_mobile_app_category_constant, +) +from google.ads.googleads.v15.resources.types import ( + mobile_device_constant as gagr_mobile_device_constant, +) +from google.ads.googleads.v15.resources.types import ( + offline_conversion_upload_client_summary as gagr_offline_conversion_upload_client_summary, +) +from google.ads.googleads.v15.resources.types import ( + offline_user_data_job as gagr_offline_user_data_job, +) +from google.ads.googleads.v15.resources.types import ( + operating_system_version_constant as gagr_operating_system_version_constant, +) +from google.ads.googleads.v15.resources.types import ( + paid_organic_search_term_view as gagr_paid_organic_search_term_view, +) +from google.ads.googleads.v15.resources.types import ( + parental_status_view as gagr_parental_status_view, +) +from google.ads.googleads.v15.resources.types import ( + per_store_view as gagr_per_store_view, +) +from google.ads.googleads.v15.resources.types import ( + product_category_constant as gagr_product_category_constant, +) +from google.ads.googleads.v15.resources.types import ( + product_group_view as gagr_product_group_view, +) +from google.ads.googleads.v15.resources.types import ( + product_link as gagr_product_link, +) +from google.ads.googleads.v15.resources.types import ( + product_link_invitation as gagr_product_link_invitation, +) +from google.ads.googleads.v15.resources.types import ( + qualifying_question as gagr_qualifying_question, +) +from google.ads.googleads.v15.resources.types import ( + recommendation as gagr_recommendation, +) +from google.ads.googleads.v15.resources.types import ( + recommendation_subscription as gagr_recommendation_subscription, +) +from google.ads.googleads.v15.resources.types import ( + remarketing_action as gagr_remarketing_action, +) +from google.ads.googleads.v15.resources.types import ( + search_term_view as gagr_search_term_view, +) +from google.ads.googleads.v15.resources.types import ( + shared_criterion as gagr_shared_criterion, +) +from google.ads.googleads.v15.resources.types import ( + shared_set as gagr_shared_set, +) +from google.ads.googleads.v15.resources.types import ( + shopping_performance_view as gagr_shopping_performance_view, +) +from google.ads.googleads.v15.resources.types import ( + smart_campaign_search_term_view as gagr_smart_campaign_search_term_view, +) +from google.ads.googleads.v15.resources.types import ( + smart_campaign_setting as gagr_smart_campaign_setting, +) +from google.ads.googleads.v15.resources.types import ( + third_party_app_analytics_link as gagr_third_party_app_analytics_link, +) +from google.ads.googleads.v15.resources.types import ( + topic_constant as gagr_topic_constant, +) +from google.ads.googleads.v15.resources.types import ( + topic_view as gagr_topic_view, +) +from google.ads.googleads.v15.resources.types import ( + travel_activity_group_view as gagr_travel_activity_group_view, +) +from google.ads.googleads.v15.resources.types import ( + travel_activity_performance_view as gagr_travel_activity_performance_view, +) +from google.ads.googleads.v15.resources.types import ( + user_interest as gagr_user_interest, +) +from google.ads.googleads.v15.resources.types import user_list as gagr_user_list +from google.ads.googleads.v15.resources.types import ( + user_location_view as gagr_user_location_view, +) +from google.ads.googleads.v15.resources.types import video as gagr_video +from google.ads.googleads.v15.resources.types import ( + webpage_view as gagr_webpage_view, +) +from google.ads.googleads.v15.services.types import ad_group_ad_label_service +from google.ads.googleads.v15.services.types import ad_group_ad_service +from google.ads.googleads.v15.services.types import ad_group_asset_service +from google.ads.googleads.v15.services.types import ( + ad_group_bid_modifier_service, +) +from google.ads.googleads.v15.services.types import ( + ad_group_criterion_customizer_service, +) +from google.ads.googleads.v15.services.types import ( + ad_group_criterion_label_service, +) +from google.ads.googleads.v15.services.types import ad_group_criterion_service +from google.ads.googleads.v15.services.types import ad_group_customizer_service +from google.ads.googleads.v15.services.types import ( + ad_group_extension_setting_service, +) +from google.ads.googleads.v15.services.types import ad_group_feed_service +from google.ads.googleads.v15.services.types import ad_group_label_service +from google.ads.googleads.v15.services.types import ad_group_service +from google.ads.googleads.v15.services.types import ad_parameter_service +from google.ads.googleads.v15.services.types import ad_service +from google.ads.googleads.v15.services.types import asset_group_asset_service +from google.ads.googleads.v15.services.types import ( + asset_group_listing_group_filter_service, +) +from google.ads.googleads.v15.services.types import asset_group_service +from google.ads.googleads.v15.services.types import asset_group_signal_service +from google.ads.googleads.v15.services.types import asset_service +from google.ads.googleads.v15.services.types import asset_set_asset_service +from google.ads.googleads.v15.services.types import asset_set_service +from google.ads.googleads.v15.services.types import audience_service +from google.ads.googleads.v15.services.types import ( + bidding_data_exclusion_service, +) +from google.ads.googleads.v15.services.types import ( + bidding_seasonality_adjustment_service, +) +from google.ads.googleads.v15.services.types import bidding_strategy_service +from google.ads.googleads.v15.services.types import campaign_asset_service +from google.ads.googleads.v15.services.types import campaign_asset_set_service +from google.ads.googleads.v15.services.types import ( + campaign_bid_modifier_service, +) +from google.ads.googleads.v15.services.types import campaign_budget_service +from google.ads.googleads.v15.services.types import ( + campaign_conversion_goal_service, +) +from google.ads.googleads.v15.services.types import campaign_criterion_service +from google.ads.googleads.v15.services.types import campaign_customizer_service +from google.ads.googleads.v15.services.types import campaign_draft_service +from google.ads.googleads.v15.services.types import ( + campaign_extension_setting_service, +) +from google.ads.googleads.v15.services.types import campaign_feed_service +from google.ads.googleads.v15.services.types import campaign_group_service +from google.ads.googleads.v15.services.types import campaign_label_service +from google.ads.googleads.v15.services.types import campaign_service +from google.ads.googleads.v15.services.types import campaign_shared_set_service +from google.ads.googleads.v15.services.types import conversion_action_service +from google.ads.googleads.v15.services.types import ( + conversion_custom_variable_service, +) +from google.ads.googleads.v15.services.types import ( + conversion_goal_campaign_config_service, +) +from google.ads.googleads.v15.services.types import ( + conversion_value_rule_service, +) +from google.ads.googleads.v15.services.types import ( + conversion_value_rule_set_service, +) +from google.ads.googleads.v15.services.types import ( + custom_conversion_goal_service, +) +from google.ads.googleads.v15.services.types import customer_asset_service +from google.ads.googleads.v15.services.types import ( + customer_conversion_goal_service, +) +from google.ads.googleads.v15.services.types import customer_customizer_service +from google.ads.googleads.v15.services.types import ( + customer_extension_setting_service, +) +from google.ads.googleads.v15.services.types import customer_feed_service +from google.ads.googleads.v15.services.types import customer_label_service +from google.ads.googleads.v15.services.types import ( + customer_negative_criterion_service, +) +from google.ads.googleads.v15.services.types import customer_service +from google.ads.googleads.v15.services.types import customizer_attribute_service +from google.ads.googleads.v15.services.types import experiment_arm_service +from google.ads.googleads.v15.services.types import experiment_service +from google.ads.googleads.v15.services.types import extension_feed_item_service +from google.ads.googleads.v15.services.types import feed_item_service +from google.ads.googleads.v15.services.types import feed_item_set_link_service +from google.ads.googleads.v15.services.types import feed_item_set_service +from google.ads.googleads.v15.services.types import feed_item_target_service +from google.ads.googleads.v15.services.types import feed_mapping_service +from google.ads.googleads.v15.services.types import feed_service +from google.ads.googleads.v15.services.types import ( + keyword_plan_ad_group_keyword_service, +) +from google.ads.googleads.v15.services.types import ( + keyword_plan_ad_group_service, +) +from google.ads.googleads.v15.services.types import ( + keyword_plan_campaign_keyword_service, +) +from google.ads.googleads.v15.services.types import ( + keyword_plan_campaign_service, +) +from google.ads.googleads.v15.services.types import keyword_plan_service +from google.ads.googleads.v15.services.types import label_service +from google.ads.googleads.v15.services.types import ( + recommendation_subscription_service, +) +from google.ads.googleads.v15.services.types import remarketing_action_service +from google.ads.googleads.v15.services.types import shared_criterion_service +from google.ads.googleads.v15.services.types import shared_set_service +from google.ads.googleads.v15.services.types import ( + smart_campaign_setting_service, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "SearchGoogleAdsRequest", + "SearchGoogleAdsResponse", + "SearchGoogleAdsStreamRequest", + "SearchGoogleAdsStreamResponse", + "GoogleAdsRow", + "MutateGoogleAdsRequest", + "MutateGoogleAdsResponse", + "MutateOperation", + "MutateOperationResponse", + }, +) + + +class SearchGoogleAdsRequest(proto.Message): + r"""Request message for + [GoogleAdsService.Search][google.ads.googleads.v15.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): + 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. + validate_only (bool): + If true, the request is validated but not + executed. + 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. + summary_row_setting (google.ads.googleads.v15.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, + ) + 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, + ) + return_total_results_count: bool = proto.Field( + proto.BOOL, + number=7, + ) + summary_row_setting: gage_summary_row_setting.SummaryRowSettingEnum.SummaryRowSetting = proto.Field( + proto.ENUM, + number=8, + enum=gage_summary_row_setting.SummaryRowSettingEnum.SummaryRowSetting, + ) + + +class SearchGoogleAdsResponse(proto.Message): + r"""Response message for + [GoogleAdsService.Search][google.ads.googleads.v15.services.GoogleAdsService.Search]. + + Attributes: + results (MutableSequence[google.ads.googleads.v15.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.v15.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. + """ + + @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, + ) + + +class SearchGoogleAdsStreamRequest(proto.Message): + r"""Request message for + [GoogleAdsService.SearchStream][google.ads.googleads.v15.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.v15.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.v15.services.GoogleAdsService.SearchStream]. + + Attributes: + results (MutableSequence[google.ads.googleads.v15.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.v15.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. + """ + + 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, + ) + + +class GoogleAdsRow(proto.Message): + r"""A returned row from the query. + Attributes: + account_budget (google.ads.googleads.v15.resources.types.AccountBudget): + The account budget in the query. + account_budget_proposal (google.ads.googleads.v15.resources.types.AccountBudgetProposal): + The account budget proposal referenced in the + query. + account_link (google.ads.googleads.v15.resources.types.AccountLink): + The AccountLink referenced in the query. + ad_group (google.ads.googleads.v15.resources.types.AdGroup): + The ad group referenced in the query. + ad_group_ad (google.ads.googleads.v15.resources.types.AdGroupAd): + The ad referenced in the query. + ad_group_ad_asset_combination_view (google.ads.googleads.v15.resources.types.AdGroupAdAssetCombinationView): + The ad group ad asset combination view in the + query. + ad_group_ad_asset_view (google.ads.googleads.v15.resources.types.AdGroupAdAssetView): + The ad group ad asset view in the query. + ad_group_ad_label (google.ads.googleads.v15.resources.types.AdGroupAdLabel): + The ad group ad label referenced in the + query. + ad_group_asset (google.ads.googleads.v15.resources.types.AdGroupAsset): + The ad group asset referenced in the query. + ad_group_asset_set (google.ads.googleads.v15.resources.types.AdGroupAssetSet): + The ad group asset set referenced in the + query. + ad_group_audience_view (google.ads.googleads.v15.resources.types.AdGroupAudienceView): + The ad group audience view referenced in the + query. + ad_group_bid_modifier (google.ads.googleads.v15.resources.types.AdGroupBidModifier): + The bid modifier referenced in the query. + ad_group_criterion (google.ads.googleads.v15.resources.types.AdGroupCriterion): + The criterion referenced in the query. + ad_group_criterion_customizer (google.ads.googleads.v15.resources.types.AdGroupCriterionCustomizer): + The ad group criterion customizer referenced + in the query. + ad_group_criterion_label (google.ads.googleads.v15.resources.types.AdGroupCriterionLabel): + The ad group criterion label referenced in + the query. + ad_group_criterion_simulation (google.ads.googleads.v15.resources.types.AdGroupCriterionSimulation): + The ad group criterion simulation referenced + in the query. + ad_group_customizer (google.ads.googleads.v15.resources.types.AdGroupCustomizer): + The ad group customizer referenced in the + query. + ad_group_extension_setting (google.ads.googleads.v15.resources.types.AdGroupExtensionSetting): + The ad group extension setting referenced in + the query. + ad_group_feed (google.ads.googleads.v15.resources.types.AdGroupFeed): + The ad group feed referenced in the query. + ad_group_label (google.ads.googleads.v15.resources.types.AdGroupLabel): + The ad group label referenced in the query. + ad_group_simulation (google.ads.googleads.v15.resources.types.AdGroupSimulation): + The ad group simulation referenced in the + query. + ad_parameter (google.ads.googleads.v15.resources.types.AdParameter): + The ad parameter referenced in the query. + age_range_view (google.ads.googleads.v15.resources.types.AgeRangeView): + The age range view referenced in the query. + ad_schedule_view (google.ads.googleads.v15.resources.types.AdScheduleView): + The ad schedule view referenced in the query. + domain_category (google.ads.googleads.v15.resources.types.DomainCategory): + The domain category referenced in the query. + asset (google.ads.googleads.v15.resources.types.Asset): + The asset referenced in the query. + asset_field_type_view (google.ads.googleads.v15.resources.types.AssetFieldTypeView): + The asset field type view referenced in the + query. + asset_group_asset (google.ads.googleads.v15.resources.types.AssetGroupAsset): + The asset group asset referenced in the + query. + asset_group_signal (google.ads.googleads.v15.resources.types.AssetGroupSignal): + The asset group signal referenced in the + query. + asset_group_listing_group_filter (google.ads.googleads.v15.resources.types.AssetGroupListingGroupFilter): + The asset group listing group filter + referenced in the query. + asset_group_product_group_view (google.ads.googleads.v15.resources.types.AssetGroupProductGroupView): + The asset group product group view referenced + in the query. + asset_group_top_combination_view (google.ads.googleads.v15.resources.types.AssetGroupTopCombinationView): + The asset group top combination view + referenced in the query. + asset_group (google.ads.googleads.v15.resources.types.AssetGroup): + The asset group referenced in the query. + asset_set_asset (google.ads.googleads.v15.resources.types.AssetSetAsset): + The asset set asset referenced in the query. + asset_set (google.ads.googleads.v15.resources.types.AssetSet): + The asset set referenced in the query. + asset_set_type_view (google.ads.googleads.v15.resources.types.AssetSetTypeView): + The asset set type view referenced in the + query. + batch_job (google.ads.googleads.v15.resources.types.BatchJob): + The batch job referenced in the query. + bidding_data_exclusion (google.ads.googleads.v15.resources.types.BiddingDataExclusion): + The bidding data exclusion referenced in the + query. + bidding_seasonality_adjustment (google.ads.googleads.v15.resources.types.BiddingSeasonalityAdjustment): + The bidding seasonality adjustment referenced + in the query. + bidding_strategy (google.ads.googleads.v15.resources.types.BiddingStrategy): + The bidding strategy referenced in the query. + bidding_strategy_simulation (google.ads.googleads.v15.resources.types.BiddingStrategySimulation): + The bidding strategy simulation referenced in + the query. + billing_setup (google.ads.googleads.v15.resources.types.BillingSetup): + The billing setup referenced in the query. + call_view (google.ads.googleads.v15.resources.types.CallView): + The call view referenced in the query. + campaign_budget (google.ads.googleads.v15.resources.types.CampaignBudget): + The campaign budget referenced in the query. + campaign (google.ads.googleads.v15.resources.types.Campaign): + The campaign referenced in the query. + campaign_asset (google.ads.googleads.v15.resources.types.CampaignAsset): + The campaign asset referenced in the query. + campaign_asset_set (google.ads.googleads.v15.resources.types.CampaignAssetSet): + The campaign asset set referenced in the + query. + campaign_audience_view (google.ads.googleads.v15.resources.types.CampaignAudienceView): + The campaign audience view referenced in the + query. + campaign_bid_modifier (google.ads.googleads.v15.resources.types.CampaignBidModifier): + The campaign bid modifier referenced in the + query. + campaign_conversion_goal (google.ads.googleads.v15.resources.types.CampaignConversionGoal): + The CampaignConversionGoal referenced in the + query. + campaign_criterion (google.ads.googleads.v15.resources.types.CampaignCriterion): + The campaign criterion referenced in the + query. + campaign_customizer (google.ads.googleads.v15.resources.types.CampaignCustomizer): + The campaign customizer referenced in the + query. + campaign_draft (google.ads.googleads.v15.resources.types.CampaignDraft): + The campaign draft referenced in the query. + campaign_extension_setting (google.ads.googleads.v15.resources.types.CampaignExtensionSetting): + The campaign extension setting referenced in + the query. + campaign_feed (google.ads.googleads.v15.resources.types.CampaignFeed): + The campaign feed referenced in the query. + campaign_group (google.ads.googleads.v15.resources.types.CampaignGroup): + Campaign Group referenced in AWQL query. + campaign_label (google.ads.googleads.v15.resources.types.CampaignLabel): + The campaign label referenced in the query. + campaign_lifecycle_goal (google.ads.googleads.v15.resources.types.CampaignLifecycleGoal): + The campaign lifecycle goal referenced in the + query. + campaign_search_term_insight (google.ads.googleads.v15.resources.types.CampaignSearchTermInsight): + The campaign search term insight referenced + in the query. + campaign_shared_set (google.ads.googleads.v15.resources.types.CampaignSharedSet): + Campaign Shared Set referenced in AWQL query. + campaign_simulation (google.ads.googleads.v15.resources.types.CampaignSimulation): + The campaign simulation referenced in the + query. + carrier_constant (google.ads.googleads.v15.resources.types.CarrierConstant): + The carrier constant referenced in the query. + change_event (google.ads.googleads.v15.resources.types.ChangeEvent): + The ChangeEvent referenced in the query. + change_status (google.ads.googleads.v15.resources.types.ChangeStatus): + The ChangeStatus referenced in the query. + combined_audience (google.ads.googleads.v15.resources.types.CombinedAudience): + The CombinedAudience referenced in the query. + audience (google.ads.googleads.v15.resources.types.Audience): + The Audience referenced in the query. + conversion_action (google.ads.googleads.v15.resources.types.ConversionAction): + The conversion action referenced in the + query. + conversion_custom_variable (google.ads.googleads.v15.resources.types.ConversionCustomVariable): + The conversion custom variable referenced in + the query. + conversion_goal_campaign_config (google.ads.googleads.v15.resources.types.ConversionGoalCampaignConfig): + The ConversionGoalCampaignConfig referenced + in the query. + conversion_value_rule (google.ads.googleads.v15.resources.types.ConversionValueRule): + The conversion value rule referenced in the + query. + conversion_value_rule_set (google.ads.googleads.v15.resources.types.ConversionValueRuleSet): + The conversion value rule set referenced in + the query. + click_view (google.ads.googleads.v15.resources.types.ClickView): + The ClickView referenced in the query. + currency_constant (google.ads.googleads.v15.resources.types.CurrencyConstant): + The currency constant referenced in the + query. + custom_audience (google.ads.googleads.v15.resources.types.CustomAudience): + The CustomAudience referenced in the query. + custom_conversion_goal (google.ads.googleads.v15.resources.types.CustomConversionGoal): + The CustomConversionGoal referenced in the + query. + custom_interest (google.ads.googleads.v15.resources.types.CustomInterest): + The CustomInterest referenced in the query. + customer (google.ads.googleads.v15.resources.types.Customer): + The customer referenced in the query. + customer_asset (google.ads.googleads.v15.resources.types.CustomerAsset): + The customer asset referenced in the query. + customer_asset_set (google.ads.googleads.v15.resources.types.CustomerAssetSet): + The customer asset set referenced in the + query. + accessible_bidding_strategy (google.ads.googleads.v15.resources.types.AccessibleBiddingStrategy): + The accessible bidding strategy referenced in + the query. + customer_customizer (google.ads.googleads.v15.resources.types.CustomerCustomizer): + The customer customizer referenced in the + query. + customer_manager_link (google.ads.googleads.v15.resources.types.CustomerManagerLink): + The CustomerManagerLink referenced in the + query. + customer_client_link (google.ads.googleads.v15.resources.types.CustomerClientLink): + The CustomerClientLink referenced in the + query. + customer_client (google.ads.googleads.v15.resources.types.CustomerClient): + The CustomerClient referenced in the query. + customer_conversion_goal (google.ads.googleads.v15.resources.types.CustomerConversionGoal): + The CustomerConversionGoal referenced in the + query. + customer_extension_setting (google.ads.googleads.v15.resources.types.CustomerExtensionSetting): + The customer extension setting referenced in + the query. + customer_feed (google.ads.googleads.v15.resources.types.CustomerFeed): + The customer feed referenced in the query. + customer_label (google.ads.googleads.v15.resources.types.CustomerLabel): + The customer label referenced in the query. + customer_lifecycle_goal (google.ads.googleads.v15.resources.types.CustomerLifecycleGoal): + The customer lifecycle goal referenced in the + query. + customer_negative_criterion (google.ads.googleads.v15.resources.types.CustomerNegativeCriterion): + The customer negative criterion referenced in + the query. + customer_search_term_insight (google.ads.googleads.v15.resources.types.CustomerSearchTermInsight): + The customer search term insight referenced + in the query. + customer_user_access (google.ads.googleads.v15.resources.types.CustomerUserAccess): + The CustomerUserAccess referenced in the + query. + customer_user_access_invitation (google.ads.googleads.v15.resources.types.CustomerUserAccessInvitation): + The CustomerUserAccessInvitation referenced + in the query. + customizer_attribute (google.ads.googleads.v15.resources.types.CustomizerAttribute): + The customizer attribute referenced in the + query. + detail_placement_view (google.ads.googleads.v15.resources.types.DetailPlacementView): + The detail placement view referenced in the + query. + detailed_demographic (google.ads.googleads.v15.resources.types.DetailedDemographic): + The detailed demographic referenced in the + query. + display_keyword_view (google.ads.googleads.v15.resources.types.DisplayKeywordView): + The display keyword view referenced in the + query. + distance_view (google.ads.googleads.v15.resources.types.DistanceView): + The distance view referenced in the query. + dynamic_search_ads_search_term_view (google.ads.googleads.v15.resources.types.DynamicSearchAdsSearchTermView): + The dynamic search ads search term view + referenced in the query. + expanded_landing_page_view (google.ads.googleads.v15.resources.types.ExpandedLandingPageView): + The expanded landing page view referenced in + the query. + extension_feed_item (google.ads.googleads.v15.resources.types.ExtensionFeedItem): + The extension feed item referenced in the + query. + feed (google.ads.googleads.v15.resources.types.Feed): + The feed referenced in the query. + feed_item (google.ads.googleads.v15.resources.types.FeedItem): + The feed item referenced in the query. + feed_item_set (google.ads.googleads.v15.resources.types.FeedItemSet): + The feed item set referenced in the query. + feed_item_set_link (google.ads.googleads.v15.resources.types.FeedItemSetLink): + The feed item set link referenced in the + query. + feed_item_target (google.ads.googleads.v15.resources.types.FeedItemTarget): + The feed item target referenced in the query. + feed_mapping (google.ads.googleads.v15.resources.types.FeedMapping): + The feed mapping referenced in the query. + feed_placeholder_view (google.ads.googleads.v15.resources.types.FeedPlaceholderView): + The feed placeholder view referenced in the + query. + gender_view (google.ads.googleads.v15.resources.types.GenderView): + The gender view referenced in the query. + geo_target_constant (google.ads.googleads.v15.resources.types.GeoTargetConstant): + The geo target constant referenced in the + query. + geographic_view (google.ads.googleads.v15.resources.types.GeographicView): + The geographic view referenced in the query. + group_placement_view (google.ads.googleads.v15.resources.types.GroupPlacementView): + The group placement view referenced in the + query. + hotel_group_view (google.ads.googleads.v15.resources.types.HotelGroupView): + The hotel group view referenced in the query. + hotel_performance_view (google.ads.googleads.v15.resources.types.HotelPerformanceView): + The hotel performance view referenced in the + query. + hotel_reconciliation (google.ads.googleads.v15.resources.types.HotelReconciliation): + The hotel reconciliation referenced in the + query. + income_range_view (google.ads.googleads.v15.resources.types.IncomeRangeView): + The income range view referenced in the + query. + keyword_view (google.ads.googleads.v15.resources.types.KeywordView): + The keyword view referenced in the query. + keyword_plan (google.ads.googleads.v15.resources.types.KeywordPlan): + The keyword plan referenced in the query. + keyword_plan_campaign (google.ads.googleads.v15.resources.types.KeywordPlanCampaign): + The keyword plan campaign referenced in the + query. + keyword_plan_campaign_keyword (google.ads.googleads.v15.resources.types.KeywordPlanCampaignKeyword): + The keyword plan campaign keyword referenced + in the query. + keyword_plan_ad_group (google.ads.googleads.v15.resources.types.KeywordPlanAdGroup): + The keyword plan ad group referenced in the + query. + keyword_plan_ad_group_keyword (google.ads.googleads.v15.resources.types.KeywordPlanAdGroupKeyword): + The keyword plan ad group referenced in the + query. + keyword_theme_constant (google.ads.googleads.v15.resources.types.KeywordThemeConstant): + The keyword theme constant referenced in the + query. + label (google.ads.googleads.v15.resources.types.Label): + The label referenced in the query. + landing_page_view (google.ads.googleads.v15.resources.types.LandingPageView): + The landing page view referenced in the + query. + language_constant (google.ads.googleads.v15.resources.types.LanguageConstant): + The language constant referenced in the + query. + location_view (google.ads.googleads.v15.resources.types.LocationView): + The location view referenced in the query. + managed_placement_view (google.ads.googleads.v15.resources.types.ManagedPlacementView): + The managed placement view referenced in the + query. + media_file (google.ads.googleads.v15.resources.types.MediaFile): + The media file referenced in the query. + local_services_verification_artifact (google.ads.googleads.v15.resources.types.LocalServicesVerificationArtifact): + The local services verification artifact + referenced in the query. + mobile_app_category_constant (google.ads.googleads.v15.resources.types.MobileAppCategoryConstant): + The mobile app category constant referenced + in the query. + mobile_device_constant (google.ads.googleads.v15.resources.types.MobileDeviceConstant): + The mobile device constant referenced in the + query. + offline_conversion_upload_client_summary (google.ads.googleads.v15.resources.types.OfflineConversionUploadClientSummary): + Offline conversion upload client summary. + offline_user_data_job (google.ads.googleads.v15.resources.types.OfflineUserDataJob): + The offline user data job referenced in the + query. + operating_system_version_constant (google.ads.googleads.v15.resources.types.OperatingSystemVersionConstant): + The operating system version constant + referenced in the query. + paid_organic_search_term_view (google.ads.googleads.v15.resources.types.PaidOrganicSearchTermView): + The paid organic search term view referenced + in the query. + qualifying_question (google.ads.googleads.v15.resources.types.QualifyingQuestion): + The qualifying question referenced in the + query. + parental_status_view (google.ads.googleads.v15.resources.types.ParentalStatusView): + The parental status view referenced in the + query. + per_store_view (google.ads.googleads.v15.resources.types.PerStoreView): + The per store view referenced in the query. + product_category_constant (google.ads.googleads.v15.resources.types.ProductCategoryConstant): + The product category referenced in the query. + product_group_view (google.ads.googleads.v15.resources.types.ProductGroupView): + The product group view referenced in the + query. + product_link (google.ads.googleads.v15.resources.types.ProductLink): + The product link referenced in the query. + product_link_invitation (google.ads.googleads.v15.resources.types.ProductLinkInvitation): + The product link invitation in the query. + recommendation (google.ads.googleads.v15.resources.types.Recommendation): + The recommendation referenced in the query. + recommendation_subscription (google.ads.googleads.v15.resources.types.RecommendationSubscription): + The recommendation subscription referenced in + the query. + search_term_view (google.ads.googleads.v15.resources.types.SearchTermView): + The search term view referenced in the query. + shared_criterion (google.ads.googleads.v15.resources.types.SharedCriterion): + The shared set referenced in the query. + shared_set (google.ads.googleads.v15.resources.types.SharedSet): + The shared set referenced in the query. + smart_campaign_setting (google.ads.googleads.v15.resources.types.SmartCampaignSetting): + The Smart campaign setting referenced in the + query. + shopping_performance_view (google.ads.googleads.v15.resources.types.ShoppingPerformanceView): + The shopping performance view referenced in + the query. + smart_campaign_search_term_view (google.ads.googleads.v15.resources.types.SmartCampaignSearchTermView): + The Smart campaign search term view + referenced in the query. + third_party_app_analytics_link (google.ads.googleads.v15.resources.types.ThirdPartyAppAnalyticsLink): + The AccountLink referenced in the query. + topic_view (google.ads.googleads.v15.resources.types.TopicView): + The topic view referenced in the query. + travel_activity_group_view (google.ads.googleads.v15.resources.types.TravelActivityGroupView): + The travel activity group view referenced in + the query. + travel_activity_performance_view (google.ads.googleads.v15.resources.types.TravelActivityPerformanceView): + The travel activity performance view + referenced in the query. + experiment (google.ads.googleads.v15.resources.types.Experiment): + The experiment referenced in the query. + experiment_arm (google.ads.googleads.v15.resources.types.ExperimentArm): + The experiment arm referenced in the query. + user_interest (google.ads.googleads.v15.resources.types.UserInterest): + The user interest referenced in the query. + life_event (google.ads.googleads.v15.resources.types.LifeEvent): + The life event referenced in the query. + user_list (google.ads.googleads.v15.resources.types.UserList): + The user list referenced in the query. + user_location_view (google.ads.googleads.v15.resources.types.UserLocationView): + The user location view referenced in the + query. + remarketing_action (google.ads.googleads.v15.resources.types.RemarketingAction): + The remarketing action referenced in the + query. + topic_constant (google.ads.googleads.v15.resources.types.TopicConstant): + The topic constant referenced in the query. + video (google.ads.googleads.v15.resources.types.Video): + The video referenced in the query. + webpage_view (google.ads.googleads.v15.resources.types.WebpageView): + The webpage view referenced in the query. + lead_form_submission_data (google.ads.googleads.v15.resources.types.LeadFormSubmissionData): + The lead form user submission referenced in + the query. + local_services_lead (google.ads.googleads.v15.resources.types.LocalServicesLead): + The local services lead referenced in the + query. + local_services_lead_conversation (google.ads.googleads.v15.resources.types.LocalServicesLeadConversation): + The local services lead + conversationreferenced in the query. + android_privacy_shared_key_google_ad_group (google.ads.googleads.v15.resources.types.AndroidPrivacySharedKeyGoogleAdGroup): + The android privacy shared key google ad + group referenced in the query. + android_privacy_shared_key_google_campaign (google.ads.googleads.v15.resources.types.AndroidPrivacySharedKeyGoogleCampaign): + The android privacy shared key google + campaign referenced in the query. + android_privacy_shared_key_google_network_type (google.ads.googleads.v15.resources.types.AndroidPrivacySharedKeyGoogleNetworkType): + The android privacy shared key google network + type referenced in the query. + metrics (google.ads.googleads.v15.common.types.Metrics): + The metrics. + segments (google.ads.googleads.v15.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_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, + ) + 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_extension_setting: gagr_ad_group_extension_setting.AdGroupExtensionSetting = proto.Field( + proto.MESSAGE, + number=112, + message=gagr_ad_group_extension_setting.AdGroupExtensionSetting, + ) + ad_group_feed: gagr_ad_group_feed.AdGroupFeed = proto.Field( + proto.MESSAGE, + number=67, + message=gagr_ad_group_feed.AdGroupFeed, + ) + 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, + ) + 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, + ) + ) + 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_extension_setting: gagr_campaign_extension_setting.CampaignExtensionSetting = proto.Field( + proto.MESSAGE, + number=113, + message=gagr_campaign_extension_setting.CampaignExtensionSetting, + ) + campaign_feed: gagr_campaign_feed.CampaignFeed = proto.Field( + proto.MESSAGE, + number=63, + message=gagr_campaign_feed.CampaignFeed, + ) + campaign_group: gagr_campaign_group.CampaignGroup = proto.Field( + proto.MESSAGE, + number=25, + message=gagr_campaign_group.CampaignGroup, + ) + 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_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, + ) + 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_extension_setting: gagr_customer_extension_setting.CustomerExtensionSetting = proto.Field( + proto.MESSAGE, + number=114, + message=gagr_customer_extension_setting.CustomerExtensionSetting, + ) + customer_feed: gagr_customer_feed.CustomerFeed = proto.Field( + proto.MESSAGE, + number=64, + message=gagr_customer_feed.CustomerFeed, + ) + 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, + ) + ) + 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, + ) + extension_feed_item: gagr_extension_feed_item.ExtensionFeedItem = ( + proto.Field( + proto.MESSAGE, + number=85, + message=gagr_extension_feed_item.ExtensionFeedItem, + ) + ) + feed: gagr_feed.Feed = proto.Field( + proto.MESSAGE, + number=46, + message=gagr_feed.Feed, + ) + feed_item: gagr_feed_item.FeedItem = proto.Field( + proto.MESSAGE, + number=50, + message=gagr_feed_item.FeedItem, + ) + feed_item_set: gagr_feed_item_set.FeedItemSet = proto.Field( + proto.MESSAGE, + number=149, + message=gagr_feed_item_set.FeedItemSet, + ) + feed_item_set_link: gagr_feed_item_set_link.FeedItemSetLink = proto.Field( + proto.MESSAGE, + number=151, + message=gagr_feed_item_set_link.FeedItemSetLink, + ) + feed_item_target: gagr_feed_item_target.FeedItemTarget = proto.Field( + proto.MESSAGE, + number=116, + message=gagr_feed_item_target.FeedItemTarget, + ) + feed_mapping: gagr_feed_mapping.FeedMapping = proto.Field( + proto.MESSAGE, + number=58, + message=gagr_feed_mapping.FeedMapping, + ) + feed_placeholder_view: gagr_feed_placeholder_view.FeedPlaceholderView = ( + proto.Field( + proto.MESSAGE, + number=97, + message=gagr_feed_placeholder_view.FeedPlaceholderView, + ) + ) + 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, + ) + 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, + ) + managed_placement_view: gagr_managed_placement_view.ManagedPlacementView = ( + proto.Field( + proto.MESSAGE, + number=53, + message=gagr_managed_placement_view.ManagedPlacementView, + ) + ) + media_file: gagr_media_file.MediaFile = proto.Field( + proto.MESSAGE, + number=90, + message=gagr_media_file.MediaFile, + ) + 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_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, + ) + 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, + ) + 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, + ) + 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_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, + ) + 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, + ) + 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.v15.services.GoogleAdsService.Mutate]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + resources are being modified. + mutate_operations (MutableSequence[google.ads.googleads.v15.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. Only errors are returned, not results. + response_content_type (google.ads.googleads.v15.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.v15.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.v15.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. + 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.v15.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.v15.services.types.AdGroupAdOperation): + An ad group ad mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_asset_operation (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.services.types.AdGroupCriterionOperation): + An ad group criterion mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_customizer_operation (google.ads.googleads.v15.services.types.AdGroupCustomizerOperation): + An ad group customizer mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_extension_setting_operation (google.ads.googleads.v15.services.types.AdGroupExtensionSettingOperation): + An ad group extension setting mutate + operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_feed_operation (google.ads.googleads.v15.services.types.AdGroupFeedOperation): + An ad group feed mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_label_operation (google.ads.googleads.v15.services.types.AdGroupLabelOperation): + An ad group label mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_group_operation (google.ads.googleads.v15.services.types.AdGroupOperation): + An ad group mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_operation (google.ads.googleads.v15.services.types.AdOperation): + An ad mutate operation. + + This field is a member of `oneof`_ ``operation``. + ad_parameter_operation (google.ads.googleads.v15.services.types.AdParameterOperation): + An ad parameter mutate operation. + + This field is a member of `oneof`_ ``operation``. + asset_operation (google.ads.googleads.v15.services.types.AssetOperation): + An asset mutate operation. + + This field is a member of `oneof`_ ``operation``. + asset_group_asset_operation (google.ads.googleads.v15.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.v15.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.v15.services.types.AssetGroupSignalOperation): + An asset group signal mutate operation. + + This field is a member of `oneof`_ ``operation``. + asset_group_operation (google.ads.googleads.v15.services.types.AssetGroupOperation): + An asset group mutate operation. + + This field is a member of `oneof`_ ``operation``. + asset_set_asset_operation (google.ads.googleads.v15.services.types.AssetSetAssetOperation): + An asset set asset mutate operation. + + This field is a member of `oneof`_ ``operation``. + asset_set_operation (google.ads.googleads.v15.services.types.AssetSetOperation): + An asset set mutate operation. + + This field is a member of `oneof`_ ``operation``. + audience_operation (google.ads.googleads.v15.services.types.AudienceOperation): + An audience mutate operation. + + This field is a member of `oneof`_ ``operation``. + bidding_data_exclusion_operation (google.ads.googleads.v15.services.types.BiddingDataExclusionOperation): + A bidding data exclusion mutate operation. + + This field is a member of `oneof`_ ``operation``. + bidding_seasonality_adjustment_operation (google.ads.googleads.v15.services.types.BiddingSeasonalityAdjustmentOperation): + A bidding seasonality adjustment mutate + operation. + + This field is a member of `oneof`_ ``operation``. + bidding_strategy_operation (google.ads.googleads.v15.services.types.BiddingStrategyOperation): + A bidding strategy mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_asset_operation (google.ads.googleads.v15.services.types.CampaignAssetOperation): + A campaign asset mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_asset_set_operation (google.ads.googleads.v15.services.types.CampaignAssetSetOperation): + A campaign asset mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_bid_modifier_operation (google.ads.googleads.v15.services.types.CampaignBidModifierOperation): + A campaign bid modifier mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_budget_operation (google.ads.googleads.v15.services.types.CampaignBudgetOperation): + A campaign budget mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_conversion_goal_operation (google.ads.googleads.v15.services.types.CampaignConversionGoalOperation): + A campaign conversion goal mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_criterion_operation (google.ads.googleads.v15.services.types.CampaignCriterionOperation): + A campaign criterion mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_customizer_operation (google.ads.googleads.v15.services.types.CampaignCustomizerOperation): + A campaign customizer mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_draft_operation (google.ads.googleads.v15.services.types.CampaignDraftOperation): + A campaign draft mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_extension_setting_operation (google.ads.googleads.v15.services.types.CampaignExtensionSettingOperation): + A campaign extension setting mutate + operation. + + This field is a member of `oneof`_ ``operation``. + campaign_feed_operation (google.ads.googleads.v15.services.types.CampaignFeedOperation): + A campaign feed mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_group_operation (google.ads.googleads.v15.services.types.CampaignGroupOperation): + A campaign group mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_label_operation (google.ads.googleads.v15.services.types.CampaignLabelOperation): + A campaign label mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_operation (google.ads.googleads.v15.services.types.CampaignOperation): + A campaign mutate operation. + + This field is a member of `oneof`_ ``operation``. + campaign_shared_set_operation (google.ads.googleads.v15.services.types.CampaignSharedSetOperation): + A campaign shared set mutate operation. + + This field is a member of `oneof`_ ``operation``. + conversion_action_operation (google.ads.googleads.v15.services.types.ConversionActionOperation): + A conversion action mutate operation. + + This field is a member of `oneof`_ ``operation``. + conversion_custom_variable_operation (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.services.types.CustomConversionGoalOperation): + A custom conversion goal mutate operation. + + This field is a member of `oneof`_ ``operation``. + customer_asset_operation (google.ads.googleads.v15.services.types.CustomerAssetOperation): + A customer asset mutate operation. + + This field is a member of `oneof`_ ``operation``. + customer_conversion_goal_operation (google.ads.googleads.v15.services.types.CustomerConversionGoalOperation): + A customer conversion goal mutate operation. + + This field is a member of `oneof`_ ``operation``. + customer_customizer_operation (google.ads.googleads.v15.services.types.CustomerCustomizerOperation): + A customer customizer mutate operation. + + This field is a member of `oneof`_ ``operation``. + customer_extension_setting_operation (google.ads.googleads.v15.services.types.CustomerExtensionSettingOperation): + A customer extension setting mutate + operation. + + This field is a member of `oneof`_ ``operation``. + customer_feed_operation (google.ads.googleads.v15.services.types.CustomerFeedOperation): + A customer feed mutate operation. + + This field is a member of `oneof`_ ``operation``. + customer_label_operation (google.ads.googleads.v15.services.types.CustomerLabelOperation): + A customer label mutate operation. + + This field is a member of `oneof`_ ``operation``. + customer_negative_criterion_operation (google.ads.googleads.v15.services.types.CustomerNegativeCriterionOperation): + A customer negative criterion mutate + operation. + + This field is a member of `oneof`_ ``operation``. + customer_operation (google.ads.googleads.v15.services.types.CustomerOperation): + A customer mutate operation. + + This field is a member of `oneof`_ ``operation``. + customizer_attribute_operation (google.ads.googleads.v15.services.types.CustomizerAttributeOperation): + A customizer attribute mutate operation. + + This field is a member of `oneof`_ ``operation``. + experiment_operation (google.ads.googleads.v15.services.types.ExperimentOperation): + An experiment mutate operation. + + This field is a member of `oneof`_ ``operation``. + experiment_arm_operation (google.ads.googleads.v15.services.types.ExperimentArmOperation): + An experiment arm mutate operation. + + This field is a member of `oneof`_ ``operation``. + extension_feed_item_operation (google.ads.googleads.v15.services.types.ExtensionFeedItemOperation): + An extension feed item mutate operation. + + This field is a member of `oneof`_ ``operation``. + feed_item_operation (google.ads.googleads.v15.services.types.FeedItemOperation): + A feed item mutate operation. + + This field is a member of `oneof`_ ``operation``. + feed_item_set_operation (google.ads.googleads.v15.services.types.FeedItemSetOperation): + A feed item set mutate operation. + + This field is a member of `oneof`_ ``operation``. + feed_item_set_link_operation (google.ads.googleads.v15.services.types.FeedItemSetLinkOperation): + A feed item set link mutate operation. + + This field is a member of `oneof`_ ``operation``. + feed_item_target_operation (google.ads.googleads.v15.services.types.FeedItemTargetOperation): + A feed item target mutate operation. + + This field is a member of `oneof`_ ``operation``. + feed_mapping_operation (google.ads.googleads.v15.services.types.FeedMappingOperation): + A feed mapping mutate operation. + + This field is a member of `oneof`_ ``operation``. + feed_operation (google.ads.googleads.v15.services.types.FeedOperation): + A feed mutate operation. + + This field is a member of `oneof`_ ``operation``. + keyword_plan_ad_group_operation (google.ads.googleads.v15.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.v15.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.v15.services.types.KeywordPlanCampaignKeywordOperation): + A keyword plan campaign keyword operation. + + This field is a member of `oneof`_ ``operation``. + keyword_plan_campaign_operation (google.ads.googleads.v15.services.types.KeywordPlanCampaignOperation): + A keyword plan campaign operation. + + This field is a member of `oneof`_ ``operation``. + keyword_plan_operation (google.ads.googleads.v15.services.types.KeywordPlanOperation): + A keyword plan operation. + + This field is a member of `oneof`_ ``operation``. + label_operation (google.ads.googleads.v15.services.types.LabelOperation): + A label mutate operation. + + This field is a member of `oneof`_ ``operation``. + recommendation_subscription_operation (google.ads.googleads.v15.services.types.RecommendationSubscriptionOperation): + A recommendation subscription mutate + operation. + + This field is a member of `oneof`_ ``operation``. + remarketing_action_operation (google.ads.googleads.v15.services.types.RemarketingActionOperation): + A remarketing action mutate operation. + + This field is a member of `oneof`_ ``operation``. + shared_criterion_operation (google.ads.googleads.v15.services.types.SharedCriterionOperation): + A shared criterion mutate operation. + + This field is a member of `oneof`_ ``operation``. + shared_set_operation (google.ads.googleads.v15.services.types.SharedSetOperation): + A shared set mutate operation. + + This field is a member of `oneof`_ ``operation``. + smart_campaign_setting_operation (google.ads.googleads.v15.services.types.SmartCampaignSettingOperation): + A Smart campaign setting mutate operation. + + This field is a member of `oneof`_ ``operation``. + user_list_operation (google.ads.googleads.v15.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_extension_setting_operation: ad_group_extension_setting_service.AdGroupExtensionSettingOperation = proto.Field( + proto.MESSAGE, + number=19, + oneof="operation", + message=ad_group_extension_setting_service.AdGroupExtensionSettingOperation, + ) + ad_group_feed_operation: ad_group_feed_service.AdGroupFeedOperation = ( + proto.Field( + proto.MESSAGE, + number=20, + oneof="operation", + message=ad_group_feed_service.AdGroupFeedOperation, + ) + ) + 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, + ) + 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_extension_setting_operation: campaign_extension_setting_service.CampaignExtensionSettingOperation = proto.Field( + proto.MESSAGE, + number=26, + oneof="operation", + message=campaign_extension_setting_service.CampaignExtensionSettingOperation, + ) + campaign_feed_operation: campaign_feed_service.CampaignFeedOperation = ( + proto.Field( + proto.MESSAGE, + number=27, + oneof="operation", + message=campaign_feed_service.CampaignFeedOperation, + ) + ) + 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_extension_setting_operation: customer_extension_setting_service.CustomerExtensionSettingOperation = proto.Field( + proto.MESSAGE, + number=30, + oneof="operation", + message=customer_extension_setting_service.CustomerExtensionSettingOperation, + ) + customer_feed_operation: customer_feed_service.CustomerFeedOperation = ( + proto.Field( + proto.MESSAGE, + number=31, + oneof="operation", + message=customer_feed_service.CustomerFeedOperation, + ) + ) + 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, + ) + ) + extension_feed_item_operation: extension_feed_item_service.ExtensionFeedItemOperation = proto.Field( + proto.MESSAGE, + number=36, + oneof="operation", + message=extension_feed_item_service.ExtensionFeedItemOperation, + ) + feed_item_operation: feed_item_service.FeedItemOperation = proto.Field( + proto.MESSAGE, + number=37, + oneof="operation", + message=feed_item_service.FeedItemOperation, + ) + feed_item_set_operation: feed_item_set_service.FeedItemSetOperation = ( + proto.Field( + proto.MESSAGE, + number=53, + oneof="operation", + message=feed_item_set_service.FeedItemSetOperation, + ) + ) + feed_item_set_link_operation: feed_item_set_link_service.FeedItemSetLinkOperation = proto.Field( + proto.MESSAGE, + number=54, + oneof="operation", + message=feed_item_set_link_service.FeedItemSetLinkOperation, + ) + feed_item_target_operation: feed_item_target_service.FeedItemTargetOperation = proto.Field( + proto.MESSAGE, + number=38, + oneof="operation", + message=feed_item_target_service.FeedItemTargetOperation, + ) + feed_mapping_operation: feed_mapping_service.FeedMappingOperation = ( + proto.Field( + proto.MESSAGE, + number=39, + oneof="operation", + message=feed_mapping_service.FeedMappingOperation, + ) + ) + feed_operation: feed_service.FeedOperation = proto.Field( + proto.MESSAGE, + number=40, + oneof="operation", + message=feed_service.FeedOperation, + ) + 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, + ) + 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. + 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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.services.types.MutateAdGroupCustomizerResult): + The result for the ad group customizer + mutate. + + This field is a member of `oneof`_ ``response``. + ad_group_extension_setting_result (google.ads.googleads.v15.services.types.MutateAdGroupExtensionSettingResult): + The result for the ad group extension setting + mutate. + + This field is a member of `oneof`_ ``response``. + ad_group_feed_result (google.ads.googleads.v15.services.types.MutateAdGroupFeedResult): + The result for the ad group feed mutate. + + This field is a member of `oneof`_ ``response``. + ad_group_label_result (google.ads.googleads.v15.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.v15.services.types.MutateAdGroupResult): + The result for the ad group mutate. + + This field is a member of `oneof`_ ``response``. + ad_parameter_result (google.ads.googleads.v15.services.types.MutateAdParameterResult): + The result for the ad parameter mutate. + + This field is a member of `oneof`_ ``response``. + ad_result (google.ads.googleads.v15.services.types.MutateAdResult): + The result for the ad mutate. + + This field is a member of `oneof`_ ``response``. + asset_result (google.ads.googleads.v15.services.types.MutateAssetResult): + The result for the asset mutate. + + This field is a member of `oneof`_ ``response``. + asset_group_asset_result (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.services.types.MutateAssetSetResult): + The result for the asset set mutate. + + This field is a member of `oneof`_ ``response``. + audience_result (google.ads.googleads.v15.services.types.MutateAudienceResult): + The result for the audience mutate. + + This field is a member of `oneof`_ ``response``. + bidding_data_exclusion_result (google.ads.googleads.v15.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.v15.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.v15.services.types.MutateBiddingStrategyResult): + The result for the bidding strategy mutate. + + This field is a member of `oneof`_ ``response``. + campaign_asset_result (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.services.types.MutateCampaignCriterionResult): + The result for the campaign criterion mutate. + + This field is a member of `oneof`_ ``response``. + campaign_customizer_result (google.ads.googleads.v15.services.types.MutateCampaignCustomizerResult): + The result for the campaign customizer + mutate. + + This field is a member of `oneof`_ ``response``. + campaign_draft_result (google.ads.googleads.v15.services.types.MutateCampaignDraftResult): + The result for the campaign draft mutate. + + This field is a member of `oneof`_ ``response``. + campaign_extension_setting_result (google.ads.googleads.v15.services.types.MutateCampaignExtensionSettingResult): + The result for the campaign extension setting + mutate. + + This field is a member of `oneof`_ ``response``. + campaign_feed_result (google.ads.googleads.v15.services.types.MutateCampaignFeedResult): + The result for the campaign feed mutate. + + This field is a member of `oneof`_ ``response``. + campaign_group_result (google.ads.googleads.v15.services.types.MutateCampaignGroupResult): + The result for the campaign group mutate. + + This field is a member of `oneof`_ ``response``. + campaign_label_result (google.ads.googleads.v15.services.types.MutateCampaignLabelResult): + The result for the campaign label mutate. + + This field is a member of `oneof`_ ``response``. + campaign_result (google.ads.googleads.v15.services.types.MutateCampaignResult): + The result for the campaign mutate. + + This field is a member of `oneof`_ ``response``. + campaign_shared_set_result (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.services.types.MutateCustomerCustomizerResult): + The result for the customer customizer + mutate. + + This field is a member of `oneof`_ ``response``. + customer_extension_setting_result (google.ads.googleads.v15.services.types.MutateCustomerExtensionSettingResult): + The result for the customer extension setting + mutate. + + This field is a member of `oneof`_ ``response``. + customer_feed_result (google.ads.googleads.v15.services.types.MutateCustomerFeedResult): + The result for the customer feed mutate. + + This field is a member of `oneof`_ ``response``. + customer_label_result (google.ads.googleads.v15.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.v15.services.types.MutateCustomerNegativeCriteriaResult): + The result for the customer negative + criterion mutate. + + This field is a member of `oneof`_ ``response``. + customer_result (google.ads.googleads.v15.services.types.MutateCustomerResult): + The result for the customer mutate. + + This field is a member of `oneof`_ ``response``. + customizer_attribute_result (google.ads.googleads.v15.services.types.MutateCustomizerAttributeResult): + The result for the customizer attribute + mutate. + + This field is a member of `oneof`_ ``response``. + experiment_result (google.ads.googleads.v15.services.types.MutateExperimentResult): + The result for the experiment mutate. + + This field is a member of `oneof`_ ``response``. + experiment_arm_result (google.ads.googleads.v15.services.types.MutateExperimentArmResult): + The result for the experiment arm mutate. + + This field is a member of `oneof`_ ``response``. + extension_feed_item_result (google.ads.googleads.v15.services.types.MutateExtensionFeedItemResult): + The result for the extension feed item + mutate. + + This field is a member of `oneof`_ ``response``. + feed_item_result (google.ads.googleads.v15.services.types.MutateFeedItemResult): + The result for the feed item mutate. + + This field is a member of `oneof`_ ``response``. + feed_item_set_result (google.ads.googleads.v15.services.types.MutateFeedItemSetResult): + The result for the feed item set mutate. + + This field is a member of `oneof`_ ``response``. + feed_item_set_link_result (google.ads.googleads.v15.services.types.MutateFeedItemSetLinkResult): + The result for the feed item set link mutate. + + This field is a member of `oneof`_ ``response``. + feed_item_target_result (google.ads.googleads.v15.services.types.MutateFeedItemTargetResult): + The result for the feed item target mutate. + + This field is a member of `oneof`_ ``response``. + feed_mapping_result (google.ads.googleads.v15.services.types.MutateFeedMappingResult): + The result for the feed mapping mutate. + + This field is a member of `oneof`_ ``response``. + feed_result (google.ads.googleads.v15.services.types.MutateFeedResult): + The result for the feed mutate. + + This field is a member of `oneof`_ ``response``. + keyword_plan_ad_group_result (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.services.types.MutateKeywordPlansResult): + The result for the keyword plan mutate. + + This field is a member of `oneof`_ ``response``. + label_result (google.ads.googleads.v15.services.types.MutateLabelResult): + The result for the label mutate. + + This field is a member of `oneof`_ ``response``. + recommendation_subscription_result (google.ads.googleads.v15.services.types.MutateRecommendationSubscriptionResult): + The result for the recommendation + subscription mutate. + + This field is a member of `oneof`_ ``response``. + remarketing_action_result (google.ads.googleads.v15.services.types.MutateRemarketingActionResult): + The result for the remarketing action mutate. + + This field is a member of `oneof`_ ``response``. + shared_criterion_result (google.ads.googleads.v15.services.types.MutateSharedCriterionResult): + The result for the shared criterion mutate. + + This field is a member of `oneof`_ ``response``. + shared_set_result (google.ads.googleads.v15.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.v15.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.v15.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_extension_setting_result: ad_group_extension_setting_service.MutateAdGroupExtensionSettingResult = proto.Field( + proto.MESSAGE, + number=19, + oneof="response", + message=ad_group_extension_setting_service.MutateAdGroupExtensionSettingResult, + ) + ad_group_feed_result: ad_group_feed_service.MutateAdGroupFeedResult = ( + proto.Field( + proto.MESSAGE, + number=20, + oneof="response", + message=ad_group_feed_service.MutateAdGroupFeedResult, + ) + ) + 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, + ) + 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_extension_setting_result: campaign_extension_setting_service.MutateCampaignExtensionSettingResult = proto.Field( + proto.MESSAGE, + number=26, + oneof="response", + message=campaign_extension_setting_service.MutateCampaignExtensionSettingResult, + ) + campaign_feed_result: campaign_feed_service.MutateCampaignFeedResult = ( + proto.Field( + proto.MESSAGE, + number=27, + oneof="response", + message=campaign_feed_service.MutateCampaignFeedResult, + ) + ) + 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_extension_setting_result: customer_extension_setting_service.MutateCustomerExtensionSettingResult = proto.Field( + proto.MESSAGE, + number=30, + oneof="response", + message=customer_extension_setting_service.MutateCustomerExtensionSettingResult, + ) + customer_feed_result: customer_feed_service.MutateCustomerFeedResult = ( + proto.Field( + proto.MESSAGE, + number=31, + oneof="response", + message=customer_feed_service.MutateCustomerFeedResult, + ) + ) + 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, + ) + ) + extension_feed_item_result: extension_feed_item_service.MutateExtensionFeedItemResult = proto.Field( + proto.MESSAGE, + number=36, + oneof="response", + message=extension_feed_item_service.MutateExtensionFeedItemResult, + ) + feed_item_result: feed_item_service.MutateFeedItemResult = proto.Field( + proto.MESSAGE, + number=37, + oneof="response", + message=feed_item_service.MutateFeedItemResult, + ) + feed_item_set_result: feed_item_set_service.MutateFeedItemSetResult = ( + proto.Field( + proto.MESSAGE, + number=53, + oneof="response", + message=feed_item_set_service.MutateFeedItemSetResult, + ) + ) + feed_item_set_link_result: feed_item_set_link_service.MutateFeedItemSetLinkResult = proto.Field( + proto.MESSAGE, + number=54, + oneof="response", + message=feed_item_set_link_service.MutateFeedItemSetLinkResult, + ) + feed_item_target_result: feed_item_target_service.MutateFeedItemTargetResult = proto.Field( + proto.MESSAGE, + number=38, + oneof="response", + message=feed_item_target_service.MutateFeedItemTargetResult, + ) + feed_mapping_result: feed_mapping_service.MutateFeedMappingResult = ( + proto.Field( + proto.MESSAGE, + number=39, + oneof="response", + message=feed_mapping_service.MutateFeedMappingResult, + ) + ) + feed_result: feed_service.MutateFeedResult = proto.Field( + proto.MESSAGE, + number=40, + oneof="response", + message=feed_service.MutateFeedResult, + ) + 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, + ) + 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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/invoice_service.py b/google/ads/googleads/v15/services/types/invoice_service.py new file mode 100644 index 000000000..cb043f13f --- /dev/null +++ b/google/ads/googleads/v15/services/types/invoice_service.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import month_of_year +from google.ads.googleads.v15.resources.types import invoice + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + 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.v15.enums.types.MonthOfYearEnum.MonthOfYear): + Required. The issue month to retrieve + invoices. + """ + + 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, + ) + + +class ListInvoicesResponse(proto.Message): + r"""Response message for + [InvoiceService.ListInvoices][google.ads.googleads.v15.services.InvoiceService.ListInvoices]. + + Attributes: + invoices (MutableSequence[google.ads.googleads.v15.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/v15/services/types/keyword_plan_ad_group_keyword_service.py b/google/ads/googleads/v15/services/types/keyword_plan_ad_group_keyword_service.py new file mode 100644 index 000000000..3caa8fdd4 --- /dev/null +++ b/google/ads/googleads/v15/services/types/keyword_plan_ad_group_keyword_service.py @@ -0,0 +1,189 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateKeywordPlanAdGroupKeywordsRequest", + "KeywordPlanAdGroupKeywordOperation", + "MutateKeywordPlanAdGroupKeywordsResponse", + "MutateKeywordPlanAdGroupKeywordResult", + }, +) + + +class MutateKeywordPlanAdGroupKeywordsRequest(proto.Message): + r"""Request message for + [KeywordPlanAdGroupKeywordService.MutateKeywordPlanAdGroupKeywords][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/keyword_plan_ad_group_service.py b/google/ads/googleads/v15/services/types/keyword_plan_ad_group_service.py new file mode 100644 index 000000000..14b74bea6 --- /dev/null +++ b/google/ads/googleads/v15/services/types/keyword_plan_ad_group_service.py @@ -0,0 +1,182 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateKeywordPlanAdGroupsRequest", + "KeywordPlanAdGroupOperation", + "MutateKeywordPlanAdGroupsResponse", + "MutateKeywordPlanAdGroupResult", + }, +) + + +class MutateKeywordPlanAdGroupsRequest(proto.Message): + r"""Request message for + [KeywordPlanAdGroupService.MutateKeywordPlanAdGroups][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/keyword_plan_campaign_keyword_service.py b/google/ads/googleads/v15/services/types/keyword_plan_campaign_keyword_service.py new file mode 100644 index 000000000..9cebdae6b --- /dev/null +++ b/google/ads/googleads/v15/services/types/keyword_plan_campaign_keyword_service.py @@ -0,0 +1,187 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateKeywordPlanCampaignKeywordsRequest", + "KeywordPlanCampaignKeywordOperation", + "MutateKeywordPlanCampaignKeywordsResponse", + "MutateKeywordPlanCampaignKeywordResult", + }, +) + + +class MutateKeywordPlanCampaignKeywordsRequest(proto.Message): + r"""Request message for + [KeywordPlanCampaignKeywordService.MutateKeywordPlanCampaignKeywords][google.ads.googleads.v15.services.KeywordPlanCampaignKeywordService.MutateKeywordPlanCampaignKeywords]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + campaign keywords are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/keyword_plan_campaign_service.py b/google/ads/googleads/v15/services/types/keyword_plan_campaign_service.py new file mode 100644 index 000000000..4212a234f --- /dev/null +++ b/google/ads/googleads/v15/services/types/keyword_plan_campaign_service.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateKeywordPlanCampaignsRequest", + "KeywordPlanCampaignOperation", + "MutateKeywordPlanCampaignsResponse", + "MutateKeywordPlanCampaignResult", + }, +) + + +class MutateKeywordPlanCampaignsRequest(proto.Message): + r"""Request message for + [KeywordPlanCampaignService.MutateKeywordPlanCampaigns][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/keyword_plan_idea_service.py b/google/ads/googleads/v15/services/types/keyword_plan_idea_service.py new file mode 100644 index 000000000..a09f1caad --- /dev/null +++ b/google/ads/googleads/v15/services/types/keyword_plan_idea_service.py @@ -0,0 +1,1123 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import criteria +from google.ads.googleads.v15.common.types import dates +from google.ads.googleads.v15.common.types import keyword_plan_common +from google.ads.googleads.v15.enums.types import keyword_match_type +from google.ads.googleads.v15.enums.types import keyword_plan_keyword_annotation +from google.ads.googleads.v15.enums.types import ( + keyword_plan_network as gage_keyword_plan_network, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "GenerateKeywordIdeasRequest", + "KeywordAndUrlSeed", + "KeywordSeed", + "SiteSeed", + "UrlSeed", + "GenerateKeywordIdeaResponse", + "GenerateKeywordIdeaResult", + "GenerateKeywordHistoricalMetricsRequest", + "GenerateKeywordHistoricalMetricsResponse", + "GenerateKeywordHistoricalMetricsResult", + "GenerateAdGroupThemesRequest", + "GenerateAdGroupThemesResponse", + "AdGroupKeywordSuggestion", + "UnusableAdGroup", + "GenerateKeywordForecastMetricsRequest", + "CampaignToForecast", + "ForecastAdGroup", + "BiddableKeyword", + "CriterionBidModifier", + "ManualCpcBiddingStrategy", + "MaximizeClicksBiddingStrategy", + "MaximizeConversionsBiddingStrategy", + "GenerateKeywordForecastMetricsResponse", + "KeywordForecastMetrics", + }, +) + + +class GenerateKeywordIdeasRequest(proto.Message): + r"""Request message for + [KeywordPlanIdeaService.GenerateKeywordIdeas][google.ads.googleads.v15.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.v15.enums.types.KeywordPlanNetworkEnum.KeywordPlanNetwork): + Targeting network. + If not set, Google Search And Partners Network + will be used. + keyword_annotation (MutableSequence[google.ads.googleads.v15.enums.types.KeywordPlanKeywordAnnotationEnum.KeywordPlanKeywordAnnotation]): + The keyword annotations to include in + response. + aggregate_metrics (google.ads.googleads.v15.common.types.KeywordPlanAggregateMetrics): + The aggregate fields to include in response. + historical_metrics_options (google.ads.googleads.v15.common.types.HistoricalMetricsOptions): + The options for historical metrics data. + keyword_and_url_seed (google.ads.googleads.v15.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.v15.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.v15.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.v15.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. + """ + + 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. + """ + + 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.v15.services.KeywordPlanIdeaService.GenerateKeywordIdeas]. + + Attributes: + results (MutableSequence[google.ads.googleads.v15.services.types.GenerateKeywordIdeaResult]): + Results of generating keyword ideas. + aggregate_metric_results (google.ads.googleads.v15.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.v15.common.types.KeywordPlanHistoricalMetrics): + The historical metrics for the keyword. + keyword_annotations (google.ads.googleads.v15.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.v15.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.v15.enums.types.KeywordPlanNetworkEnum.KeywordPlanNetwork): + Targeting network. + If not set, Google Search And Partners Network + will be used. + aggregate_metrics (google.ads.googleads.v15.common.types.KeywordPlanAggregateMetrics): + The aggregate fields to include in response. + historical_metrics_options (google.ads.googleads.v15.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.v15.services.KeywordPlanIdeaService.GenerateKeywordHistoricalMetrics]. + + Attributes: + results (MutableSequence[google.ads.googleads.v15.services.types.GenerateKeywordHistoricalMetricsResult]): + List of keywords and their historical + metrics. + aggregate_metric_results (google.ads.googleads.v15.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.v15.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.v15.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.v15.services.KeywordPlanIdeaService.GenerateAdGroupThemes]. + + Attributes: + ad_group_keyword_suggestions (MutableSequence[google.ads.googleads.v15.services.types.AdGroupKeywordSuggestion]): + A list of suggested AdGroup/keyword pairings. + unusable_ad_groups (MutableSequence[google.ads.googleads.v15.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.v15.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]. + + .. _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.v15.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.v15.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. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + 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_modifiers (MutableSequence[google.ads.googleads.v15.services.types.CriterionBidModifier]): + Locations to be targeted. Locations must be + unique. + keyword_plan_network (google.ads.googleads.v15.enums.types.KeywordPlanNetworkEnum.KeywordPlanNetwork): + Required. The network used for targeting. + negative_keywords (MutableSequence[google.ads.googleads.v15.common.types.KeywordInfo]): + The list of negative keywords to be used in + the campaign when doing the forecast. + bidding_strategy (google.ads.googleads.v15.services.types.CampaignToForecast.CampaignBiddingStrategy): + Required. The bidding strategy for the + campaign. + conversion_rate (float): + The expected conversion rate (number of + conversions divided by number of total clicks) + as defined by the user. This value is expressed + as a decimal value, so an expected conversion + rate of 2% should be entered as 0.02. If left + empty, an estimated conversion rate will be + used. + + This field is a member of `oneof`_ ``_conversion_rate``. + ad_groups (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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_modifiers: MutableSequence[ + "CriterionBidModifier" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="CriterionBidModifier", + ) + keyword_plan_network: gage_keyword_plan_network.KeywordPlanNetworkEnum.KeywordPlanNetwork = proto.Field( + proto.ENUM, + number=3, + enum=gage_keyword_plan_network.KeywordPlanNetworkEnum.KeywordPlanNetwork, + ) + negative_keywords: MutableSequence[ + criteria.KeywordInfo + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=criteria.KeywordInfo, + ) + bidding_strategy: CampaignBiddingStrategy = proto.Field( + proto.MESSAGE, + number=5, + message=CampaignBiddingStrategy, + ) + conversion_rate: float = proto.Field( + proto.DOUBLE, + number=6, + optional=True, + ) + 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. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + max_cpc_bid_micros (int): + The max cpc to use for the ad group when + generating forecasted traffic. This value will + override the max cpc value set in the bidding + strategy. Only specify this field for bidding + strategies that max cpc values. + + This field is a member of `oneof`_ ``_max_cpc_bid_micros``. + biddable_keywords (MutableSequence[google.ads.googleads.v15.services.types.BiddableKeyword]): + Required. The list of biddable keywords to be + used in the ad group when doing the forecast. + Requires at least one keyword. + negative_keywords (MutableSequence[google.ads.googleads.v15.common.types.KeywordInfo]): + The details of the keyword. You should + specify both the keyword text and match type. + """ + + max_cpc_bid_micros: int = proto.Field( + proto.INT64, + number=1, + optional=True, + ) + biddable_keywords: MutableSequence["BiddableKeyword"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="BiddableKeyword", + ) + negative_keywords: MutableSequence[ + criteria.KeywordInfo + ] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=criteria.KeywordInfo, + ) + + +class BiddableKeyword(proto.Message): + r"""A biddable keyword part of an ad group. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + keyword (google.ads.googleads.v15.common.types.KeywordInfo): + Required. Keyword. Must have text and match + type. + max_cpc_bid_micros (int): + A max cpc bid in micros that overrides the ad + group level max cpc bid in forecast simulation. + This value will override the max cpc value set + in the bidding strategy and ad group. Only + specify this field for bidding strategies that + support max cpc values. + + This field is a member of `oneof`_ ``_max_cpc_bid_micros``. + """ + + keyword: criteria.KeywordInfo = proto.Field( + proto.MESSAGE, + number=1, + message=criteria.KeywordInfo, + ) + max_cpc_bid_micros: int = proto.Field( + proto.INT64, + number=2, + optional=True, + ) + + +class CriterionBidModifier(proto.Message): + r"""Location Criterion bid modifier. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + geo_target_constant (str): + The resource name of the geo location to target. The + resource name is of the format + "geoTargetConstants/{criterion_id}". + bid_modifier (float): + The associated multiplier for the criterion_id. If set, this + value cannot be 0. + + This field is a member of `oneof`_ ``_bid_modifier``. + """ + + geo_target_constant: str = proto.Field( + proto.STRING, + number=1, + ) + bid_modifier: float = proto.Field( + proto.DOUBLE, + number=2, + optional=True, + ) + + +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]. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + campaign_forecast_metrics (google.ads.googleads.v15.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: + impressions (float): + The total number of impressions. + + This field is a member of `oneof`_ ``_impressions``. + click_through_rate (float): + The average click through rate. Available + only if impressions > 0. + + This field is a member of `oneof`_ ``_click_through_rate``. + 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 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: clicks \* conversion_rate. + + This field is a member of `oneof`_ ``_conversions``. + conversion_rate (float): + Forecasted conversion rate. + + This field is a member of `oneof`_ ``_conversion_rate``. + average_cpa_micros (int): + Average cost per acquisition calculated as cost_micros / + conversions. + + This field is a member of `oneof`_ ``_average_cpa_micros``. + """ + + impressions: float = proto.Field( + proto.DOUBLE, + number=1, + optional=True, + ) + click_through_rate: float = proto.Field( + proto.DOUBLE, + number=2, + optional=True, + ) + 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, + ) + conversion_rate: float = proto.Field( + proto.DOUBLE, + number=7, + 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/v15/services/types/keyword_plan_service.py b/google/ads/googleads/v15/services/types/keyword_plan_service.py new file mode 100644 index 000000000..e0438354c --- /dev/null +++ b/google/ads/googleads/v15/services/types/keyword_plan_service.py @@ -0,0 +1,176 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateKeywordPlansRequest", + "KeywordPlanOperation", + "MutateKeywordPlansResponse", + "MutateKeywordPlansResult", + }, +) + + +class MutateKeywordPlansRequest(proto.Message): + r"""Request message for + [KeywordPlanService.MutateKeywordPlans][google.ads.googleads.v15.services.KeywordPlanService.MutateKeywordPlans]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + keyword plans are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/keyword_theme_constant_service.py b/google/ads/googleads/v15/services/types/keyword_theme_constant_service.py new file mode 100644 index 000000000..4a6ff30dc --- /dev/null +++ b/google/ads/googleads/v15/services/types/keyword_theme_constant_service.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import keyword_theme_constant + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "SuggestKeywordThemeConstantsRequest", + "SuggestKeywordThemeConstantsResponse", + }, +) + + +class SuggestKeywordThemeConstantsRequest(proto.Message): + r"""Request message for + [KeywordThemeConstantService.SuggestKeywordThemeConstants][google.ads.googleads.v15.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.v15.services.KeywordThemeConstantService.SuggestKeywordThemeConstants]. + + Attributes: + keyword_theme_constants (MutableSequence[google.ads.googleads.v15.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/v15/services/types/label_service.py b/google/ads/googleads/v15/services/types/label_service.py new file mode 100644 index 000000000..6c19b29d4 --- /dev/null +++ b/google/ads/googleads/v15/services/types/label_service.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateLabelsRequest", + "LabelOperation", + "MutateLabelsResponse", + "MutateLabelResult", + }, +) + + +class MutateLabelsRequest(proto.Message): + r"""Request message for + [LabelService.MutateLabels][google.ads.googleads.v15.services.LabelService.MutateLabels]. + + Attributes: + customer_id (str): + Required. ID of the customer whose labels are + being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/offline_user_data_job_service.py b/google/ads/googleads/v15/services/types/offline_user_data_job_service.py new file mode 100644 index 000000000..98421ddce --- /dev/null +++ b/google/ads/googleads/v15/services/types/offline_user_data_job_service.py @@ -0,0 +1,253 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import offline_user_data +from google.ads.googleads.v15.resources.types import offline_user_data_job +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "CreateOfflineUserDataJobRequest", + "CreateOfflineUserDataJobResponse", + "RunOfflineUserDataJobRequest", + "AddOfflineUserDataJobOperationsRequest", + "OfflineUserDataJobOperation", + "AddOfflineUserDataJobOperationsResponse", + }, +) + + +class CreateOfflineUserDataJobRequest(proto.Message): + r"""Request message for + [OfflineUserDataJobService.CreateOfflineUserDataJob][google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/payments_account_service.py b/google/ads/googleads/v15/services/types/payments_account_service.py new file mode 100644 index 000000000..fcadee1c2 --- /dev/null +++ b/google/ads/googleads/v15/services/types/payments_account_service.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.resources.types import payments_account + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + 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.v15.services.PaymentsAccountService.ListPaymentsAccounts]. + + Attributes: + payments_accounts (MutableSequence[google.ads.googleads.v15.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/v15/services/types/product_link_invitation_service.py b/google/ads/googleads/v15/services/types/product_link_invitation_service.py new file mode 100644 index 000000000..472e4d770 --- /dev/null +++ b/google/ads/googleads/v15/services/types/product_link_invitation_service.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.enums.types import ( + product_link_invitation_status as gage_product_link_invitation_status, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "UpdateProductLinkInvitationRequest", + "UpdateProductLinkInvitationResponse", + }, +) + + +class UpdateProductLinkInvitationRequest(proto.Message): + r"""Request message for + [ProductLinkInvitationService.UpdateProductLinkInvitation][google.ads.googleads.v15.services.ProductLinkInvitationService.UpdateProductLinkInvitation]. + + Attributes: + customer_id (str): + Required. The ID of the customer being + modified. + product_link_invitation_status (google.ads.googleads.v15.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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/product_link_service.py b/google/ads/googleads/v15/services/types/product_link_service.py new file mode 100644 index 000000000..ced54b8b7 --- /dev/null +++ b/google/ads/googleads/v15/services/types/product_link_service.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.v15.resources.types import ( + product_link as gagr_product_link, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "CreateProductLinkRequest", + "CreateProductLinkResponse", + "RemoveProductLinkRequest", + "RemoveProductLinkResponse", + }, +) + + +class CreateProductLinkRequest(proto.Message): + r"""Request message for + [ProductLinkService.CreateProductLink][google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/reach_plan_service.py b/google/ads/googleads/v15/services/types/reach_plan_service.py new file mode 100644 index 000000000..fc57f6f08 --- /dev/null +++ b/google/ads/googleads/v15/services/types/reach_plan_service.py @@ -0,0 +1,1285 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import criteria +from google.ads.googleads.v15.common.types import dates +from google.ads.googleads.v15.enums.types import frequency_cap_time_unit +from google.ads.googleads.v15.enums.types import reach_plan_age_range +from google.ads.googleads.v15.enums.types import reach_plan_network +from google.ads.googleads.v15.enums.types import reach_plan_surface +from google.ads.googleads.v15.enums.types import target_frequency_time_unit + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "ListPlannableLocationsRequest", + "ListPlannableLocationsResponse", + "PlannableLocation", + "ListPlannableProductsRequest", + "ListPlannableProductsResponse", + "ProductMetadata", + "PlannableTargeting", + "GenerateReachForecastRequest", + "EffectiveFrequencyLimit", + "FrequencyCap", + "Targeting", + "CampaignDuration", + "PlannedProduct", + "GenerateReachForecastResponse", + "ReachCurve", + "ReachForecast", + "Forecast", + "PlannedProductReachForecast", + "PlannedProductForecast", + "OnTargetAudienceMetrics", + "EffectiveFrequencyBreakdown", + "ForecastMetricOptions", + "AudienceTargeting", + "AdvancedProductTargeting", + "YouTubeSelectSettings", + "YouTubeSelectLineUp", + "SurfaceTargetingCombinations", + "SurfaceTargeting", + "TargetFrequencySettings", + }, +) + + +class ListPlannableLocationsRequest(proto.Message): + r"""Request message for + [ReachPlanService.ListPlannableLocations][google.ads.googleads.v15.services.ReachPlanService.ListPlannableLocations]. + + """ + + +class ListPlannableLocationsResponse(proto.Message): + r"""The list of plannable locations. + Attributes: + plannable_locations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.services.ReachPlanService.ListPlannableLocations]. + """ + + plannable_location_id: str = proto.Field( + proto.STRING, + number=2, + ) + + +class ListPlannableProductsResponse(proto.Message): + r"""A response with all available products. + Attributes: + product_metadata (MutableSequence[google.ads.googleads.v15.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: + BUMPER, TRUEVIEW_IN_STREAM). To list the available plannable + product codes use + [ReachPlanService.ListPlannableProducts][google.ads.googleads.v15.services.ReachPlanService.ListPlannableProducts]. + + This field is a member of `oneof`_ ``_plannable_product_code``. + plannable_product_name (str): + The name associated with the ad product. + plannable_targeting (google.ads.googleads.v15.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_targeting: "PlannableTargeting" = proto.Field( + proto.MESSAGE, + number=2, + message="PlannableTargeting", + ) + + +class PlannableTargeting(proto.Message): + r"""The targeting for which traffic metrics will be reported. + Attributes: + age_ranges (MutableSequence[google.ads.googleads.v15.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.v15.common.types.GenderInfo]): + Targetable genders for the ad product. + devices (MutableSequence[google.ads.googleads.v15.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.v15.enums.types.ReachPlanNetworkEnum.ReachPlanNetwork]): + Targetable networks for the ad product. + youtube_select_lineups (MutableSequence[google.ads.googleads.v15.services.types.YouTubeSelectLineUp]): + Targetable YouTube Select Lineups for the ad + product. + surface_targeting (google.ads.googleads.v15.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_lineups: MutableSequence[ + "YouTubeSelectLineUp" + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="YouTubeSelectLineUp", + ) + surface_targeting: "SurfaceTargetingCombinations" = proto.Field( + proto.MESSAGE, + number=6, + message="SurfaceTargetingCombinations", + ) + + +class GenerateReachForecastRequest(proto.Message): + r"""Request message for + [ReachPlanService.GenerateReachForecast][google.ads.googleads.v15.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.v15.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 in v4 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.v15.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.v15.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.v15.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.v15.services.types.PlannedProduct]): + Required. The products to be forecast. + The max number of allowed planned products is + 15. + forecast_metric_options (google.ads.googleads.v15.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``. + """ + + 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, + ) + + +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.v15.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.v15.services.ReachPlanService.ListPlannableLocations]. + + Requests must set either this field or + ``plannable_location_ids``. + + This field is deprecated as of V12 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.v15.services.ReachPlanService.ListPlannableLocations]. + + Requests must set either this field or + ``plannable_location_id``. + age_range (google.ads.googleads.v15.enums.types.ReachPlanAgeRangeEnum.ReachPlanAgeRange): + Targeted age range. + An unset value is equivalent to targeting all + ages. + genders (MutableSequence[google.ads.googleads.v15.common.types.GenderInfo]): + Targeted genders. + An unset value is equivalent to targeting MALE + and FEMALE. + devices (MutableSequence[google.ads.googleads.v15.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.v15.services.ReachPlanService.ListPlannableProducts]. + network (google.ads.googleads.v15.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.v15.services.ReachPlanService.ListPlannableProducts]. + audience_targeting (google.ads.googleads.v15.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.v15.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.v15.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``. + advanced_product_targeting (google.ads.googleads.v15.services.types.AdvancedProductTargeting): + Targeting settings for the selected product. To list the + available targeting for each product use + [ReachPlanService.ListPlannableProducts][google.ads.googleads.v15.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, + ) + 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.v15.services.types.OnTargetAudienceMetrics): + Reference on target audiences for this curve. + reach_curve (google.ads.googleads.v15.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.v15.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.v15.services.types.Forecast): + Forecasted traffic metrics for this point. + planned_product_reach_forecasts (MutableSequence[google.ads.googleads.v15.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.v15.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``. + views (int): + Number of ad views forecasted for the + specified product and targeting. A 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 views. + + This field is a member of `oneof`_ ``_views``. + """ + + 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, + ) + views: int = proto.Field( + proto.INT64, + number=15, + 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.v15.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``. + views (int): + Number of ad views forecasted for the + specified product and targeting. A 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 views. + + This field is a member of `oneof`_ ``_views``. + """ + + 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, + ) + views: int = proto.Field( + proto.INT64, + number=11, + optional=True, + ) + + +class OnTargetAudienceMetrics(proto.Message): + r"""Audience metrics for the planned products. + These metrics consider the following targeting dimensions: + + - Location + - PlannableAgeRange + - Gender + + .. _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.v15.common.types.UserInterestInfo]): + List of audiences based on user interests to + be targeted. + """ + + user_interest: MutableSequence[ + criteria.UserInterestInfo + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=criteria.UserInterestInfo, + ) + + +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.v15.services.types.SurfaceTargeting): + Surface targeting settings for this product. + target_frequency_settings (google.ads.googleads.v15.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.v15.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 SurfaceTargetingCombinations(proto.Message): + r"""The surface targeting combinations available for an ad + product. + + Attributes: + default_targeting (google.ads.googleads.v15.services.types.SurfaceTargeting): + Default surface targeting applied to the ad + product. + available_targeting_combinations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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/v15/services/types/recommendation_service.py b/google/ads/googleads/v15/services/types/recommendation_service.py new file mode 100644 index 000000000..853709def --- /dev/null +++ b/google/ads/googleads/v15/services/types/recommendation_service.py @@ -0,0 +1,970 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import extensions +from google.ads.googleads.v15.enums.types import keyword_match_type +from google.ads.googleads.v15.resources.types import ad as gagr_ad +from google.ads.googleads.v15.resources.types import asset +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "ApplyRecommendationRequest", + "ApplyRecommendationOperation", + "ApplyRecommendationResponse", + "ApplyRecommendationResult", + "DismissRecommendationRequest", + "DismissRecommendationResponse", + }, +) + + +class ApplyRecommendationRequest(proto.Message): + r"""Request message for + [RecommendationService.ApplyRecommendation][google.ads.googleads.v15.services.RecommendationService.ApplyRecommendation]. + + Attributes: + customer_id (str): + Required. The ID of the customer with the + recommendation. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.services.types.ApplyRecommendationOperation.ForecastingSetTargetRoasParameters): + Parameters to use when applying set target + ROAS 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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.""" + 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.v15.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.v15.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.v15.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, + ) + + 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, + ) + + +class ApplyRecommendationResponse(proto.Message): + r"""Response message for + [RecommendationService.ApplyRecommendation][google.ads.googleads.v15.services.RecommendationService.ApplyRecommendation]. + + Attributes: + results (MutableSequence[google.ads.googleads.v15.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.v15.services.RecommendationService.DismissRecommendation]. + + Attributes: + customer_id (str): + Required. The ID of the customer with the + recommendation. + operations (MutableSequence[google.ads.googleads.v15.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.v15.services.RecommendationService.DismissRecommendation]. + + Attributes: + results (MutableSequence[google.ads.googleads.v15.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, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/recommendation_subscription_service.py b/google/ads/googleads/v15/services/types/recommendation_subscription_service.py new file mode 100644 index 000000000..2a8db2f83 --- /dev/null +++ b/google/ads/googleads/v15/services/types/recommendation_subscription_service.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateRecommendationSubscriptionRequest", + "RecommendationSubscriptionOperation", + "MutateRecommendationSubscriptionResponse", + "MutateRecommendationSubscriptionResult", + }, +) + + +class MutateRecommendationSubscriptionRequest(proto.Message): + r"""Request message for + [RecommendationSubscriptionService.MutateRecommendationSubscription] + + Attributes: + customer_id (str): + Required. The ID of the subscribing customer. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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] + + 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.v15.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.v15.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] + + Attributes: + results (MutableSequence[google.ads.googleads.v15.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] + + Attributes: + resource_name (str): + Resource name of the subscription that was + modified. + recommendation_subscription (google.ads.googleads.v15.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/v15/services/types/remarketing_action_service.py b/google/ads/googleads/v15/services/types/remarketing_action_service.py new file mode 100644 index 000000000..7918129ec --- /dev/null +++ b/google/ads/googleads/v15/services/types/remarketing_action_service.py @@ -0,0 +1,166 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateRemarketingActionsRequest", + "RemarketingActionOperation", + "MutateRemarketingActionsResponse", + "MutateRemarketingActionResult", + }, +) + + +class MutateRemarketingActionsRequest(proto.Message): + r"""Request message for + [RemarketingActionService.MutateRemarketingActions][google.ads.googleads.v15.services.RemarketingActionService.MutateRemarketingActions]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose + remarketing actions are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/shared_criterion_service.py b/google/ads/googleads/v15/services/types/shared_criterion_service.py new file mode 100644 index 000000000..52d0de292 --- /dev/null +++ b/google/ads/googleads/v15/services/types/shared_criterion_service.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.resources.types import ( + shared_criterion as gagr_shared_criterion, +) +from google.rpc import status_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateSharedCriteriaRequest", + "SharedCriterionOperation", + "MutateSharedCriteriaResponse", + "MutateSharedCriterionResult", + }, +) + + +class MutateSharedCriteriaRequest(proto.Message): + r"""Request message for + [SharedCriterionService.MutateSharedCriteria][google.ads.googleads.v15.services.SharedCriterionService.MutateSharedCriteria]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose shared + criteria are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/shared_set_service.py b/google/ads/googleads/v15/services/types/shared_set_service.py new file mode 100644 index 000000000..bcb2d606e --- /dev/null +++ b/google/ads/googleads/v15/services/types/shared_set_service.py @@ -0,0 +1,197 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateSharedSetsRequest", + "SharedSetOperation", + "MutateSharedSetsResponse", + "MutateSharedSetResult", + }, +) + + +class MutateSharedSetsRequest(proto.Message): + r"""Request message for + [SharedSetService.MutateSharedSets][google.ads.googleads.v15.services.SharedSetService.MutateSharedSets]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose shared + sets are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/smart_campaign_setting_service.py b/google/ads/googleads/v15/services/types/smart_campaign_setting_service.py new file mode 100644 index 000000000..e6ed5b90d --- /dev/null +++ b/google/ads/googleads/v15/services/types/smart_campaign_setting_service.py @@ -0,0 +1,395 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + response_content_type as gage_response_content_type, +) +from google.ads.googleads.v15.enums.types import ( + smart_campaign_not_eligible_reason, +) +from google.ads.googleads.v15.enums.types import ( + smart_campaign_status as gage_smart_campaign_status, +) +from google.ads.googleads.v15.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.v15.services", + marshal="google.ads.googleads.v15", + 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.v15.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.v15.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.v15.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.v15.enums.types.SmartCampaignStatusEnum.SmartCampaignStatus): + The status of this Smart campaign. + not_eligible_details (google.ads.googleads.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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.v15.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/v15/services/types/smart_campaign_suggest_service.py b/google/ads/googleads/v15/services/types/smart_campaign_suggest_service.py new file mode 100644 index 000000000..21ac78781 --- /dev/null +++ b/google/ads/googleads/v15/services/types/smart_campaign_suggest_service.py @@ -0,0 +1,421 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import ad_type_infos +from google.ads.googleads.v15.common.types import criteria +from google.ads.googleads.v15.resources.types import ( + keyword_theme_constant as gagr_keyword_theme_constant, +) + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "SuggestSmartCampaignBudgetOptionsRequest", + "SmartCampaignSuggestionInfo", + "SuggestSmartCampaignBudgetOptionsResponse", + "SuggestSmartCampaignAdRequest", + "SuggestSmartCampaignAdResponse", + "SuggestKeywordThemesRequest", + "SuggestKeywordThemesResponse", + }, +) + + +class SuggestSmartCampaignBudgetOptionsRequest(proto.Message): + r"""Request message for + [SmartCampaignSuggestService.SuggestSmartCampaignBudgetOptions][google.ads.googleads.v15.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.v15.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.v15.common.types.AdScheduleInfo]): + Optional. The business ad schedule. + keyword_themes (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.services.types.SmartCampaignSuggestionInfo.LocationList): + Optional. The targeting geo location by + locations. + + This field is a member of `oneof`_ ``geo_target``. + proximity (google.ads.googleads.v15.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.v15.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.v15.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.v15.services.types.SuggestSmartCampaignBudgetOptionsResponse.BudgetOption): + Optional. The lowest budget option. + + This field is a member of `oneof`_ ``_low``. + recommended (google.ads.googleads.v15.services.types.SuggestSmartCampaignBudgetOptionsResponse.BudgetOption): + Optional. The recommended budget option. + + This field is a member of `oneof`_ ``_recommended``. + high (google.ads.googleads.v15.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.v15.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.v15.services.SmartCampaignSuggestService.SuggestSmartCampaignAd]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + suggestion_info (google.ads.googleads.v15.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.v15.services.SmartCampaignSuggestService.SuggestSmartCampaignAd]. + + Attributes: + ad_info (google.ads.googleads.v15.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.v15.services.SmartCampaignSuggestService.SuggestKeywordThemes]. + + Attributes: + customer_id (str): + Required. The ID of the customer. + suggestion_info (google.ads.googleads.v15.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.v15.services.SmartCampaignSuggestService.SuggestKeywordThemes]. + + Attributes: + keyword_themes (MutableSequence[google.ads.googleads.v15.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.v15.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/v15/services/types/third_party_app_analytics_link_service.py b/google/ads/googleads/v15/services/types/third_party_app_analytics_link_service.py new file mode 100644 index 000000000..bd68be0d6 --- /dev/null +++ b/google/ads/googleads/v15/services/types/third_party_app_analytics_link_service.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "RegenerateShareableLinkIdRequest", + "RegenerateShareableLinkIdResponse", + }, +) + + +class RegenerateShareableLinkIdRequest(proto.Message): + r"""Request message for + [ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId][google.ads.googleads.v15.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.v15.services.ThirdPartyAppAnalyticsLinkService.RegenerateShareableLinkId]. + + """ + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v15/services/types/travel_asset_suggestion_service.py b/google/ads/googleads/v15/services/types/travel_asset_suggestion_service.py new file mode 100644 index 000000000..29d0a04db --- /dev/null +++ b/google/ads/googleads/v15/services/types/travel_asset_suggestion_service.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.enums.types import ( + asset_field_type as gage_asset_field_type, +) +from google.ads.googleads.v15.enums.types import call_to_action_type +from google.ads.googleads.v15.enums.types import hotel_asset_suggestion_status + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "SuggestTravelAssetsRequest", + "SuggestTravelAssetsResponse", + "HotelAssetSuggestion", + "HotelTextAsset", + "HotelImageAsset", + }, +) + + +class SuggestTravelAssetsRequest(proto.Message): + r"""Request message for + [TravelAssetSuggestionService.SuggestTravelAssets][google.ads.googleads.v15.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.v15.services.TravelAssetSuggestionService.SuggestTravelAssets]. + + Attributes: + hotel_asset_suggestions (MutableSequence[google.ads.googleads.v15.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.v15.enums.types.CallToActionTypeEnum.CallToActionType): + Call to action type. + text_assets (MutableSequence[google.ads.googleads.v15.services.types.HotelTextAsset]): + Text assets such as headline, description, + etc. + image_assets (MutableSequence[google.ads.googleads.v15.services.types.HotelImageAsset]): + Image assets such as + landscape/portrait/square, etc. + status (google.ads.googleads.v15.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.v15.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.v15.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/v15/services/types/user_data_service.py b/google/ads/googleads/v15/services/types/user_data_service.py new file mode 100644 index 000000000..07791a405 --- /dev/null +++ b/google/ads/googleads/v15/services/types/user_data_service.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.common.types import offline_user_data + + +__protobuf__ = proto.module( + package="google.ads.googleads.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "UploadUserDataRequest", + "UserDataOperation", + "UploadUserDataResponse", + }, +) + + +class UploadUserDataRequest(proto.Message): + r"""Request message for + [UserDataService.UploadUserData][google.ads.googleads.v15.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.v15.services.types.UserDataOperation]): + Required. The list of operations to be done. + customer_match_user_list_metadata (google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/services/types/user_list_service.py b/google/ads/googleads/v15/services/types/user_list_service.py new file mode 100644 index 000000000..f65f49a11 --- /dev/null +++ b/google/ads/googleads/v15/services/types/user_list_service.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF 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.v15.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.v15.services", + marshal="google.ads.googleads.v15", + manifest={ + "MutateUserListsRequest", + "UserListOperation", + "MutateUserListsResponse", + "MutateUserListResult", + }, +) + + +class MutateUserListsRequest(proto.Message): + r"""Request message for + [UserListService.MutateUserLists][google.ads.googleads.v15.services.UserListService.MutateUserLists]. + + Attributes: + customer_id (str): + Required. The ID of the customer whose user + lists are being modified. + operations (MutableSequence[google.ads.googleads.v15.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.v15.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.v15.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.v15.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/v15/types/__init__.py b/google/ads/googleads/v15/types/__init__.py new file mode 100644 index 000000000..89a37dc92 --- /dev/null +++ b/google/ads/googleads/v15/types/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/setup.py b/setup.py index cf7a537f5..abad406cd 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ "proto-plus >= 1.19.6, < 2.0.0", "PyYAML >= 5.1, < 7.0", "setuptools >= 40.3.0", - "protobuf >= 3.12.0, < 5.0.0dev, !=3.18.*, !=3.19.*", + "protobuf >= 3.12.0, < 5.0.0, !=3.18.*, !=3.19.*", ] with io.open("README.rst", "r", encoding="utf-8") as readme_file: @@ -36,7 +36,7 @@ setup( name="google-ads", - version="22.0.0", + version="22.1.0", author="Google LLC", author_email="googleapis-packages@google.com", classifiers=[ @@ -53,10 +53,14 @@ ], description="Client library for the Google Ads API", include_package_data=True, - python_requires=">=3.7", + python_requires=">=3.7, <3.12", long_description=long_description, install_requires=install_requires, - extras_require={"tests": ["nox >= 2020.12.31, < 2022.6",]}, + extras_require={ + "tests": [ + "nox >= 2020.12.31, < 2022.6", + ] + }, license="Apache 2.0", packages=find_packages( exclude=["examples", "examples.*", "tests", "tests.*"] diff --git a/tests/client_test.py b/tests/client_test.py index 35b9296a5..52e81c220 100644 --- a/tests/client_test.py +++ b/tests/client_test.py @@ -110,6 +110,7 @@ def test_get_client_kwargs_login_customer_id(self): "logging_config": None, "linked_customer_id": self.linked_customer_id, "http_proxy": None, + "use_cloud_org_for_api_access": None, }, ) @@ -142,6 +143,7 @@ def test_get_client_kwargs_login_customer_id_as_None(self): "logging_config": None, "linked_customer_id": None, "http_proxy": None, + "use_cloud_org_for_api_access": None, }, ) @@ -174,6 +176,7 @@ def test_get_client_kwargs_linked_customer_id(self): "logging_config": None, "linked_customer_id": self.linked_customer_id, "http_proxy": None, + "use_cloud_org_for_api_access": None, }, ) @@ -206,6 +209,7 @@ def test_get_client_kwargs_linked_customer_id_as_none(self): "logging_config": None, "login_customer_id": None, "http_proxy": None, + "use_cloud_org_for_api_access": None, }, ) @@ -238,6 +242,7 @@ def test_get_client_kwargs(self): "logging_config": None, "linked_customer_id": None, "http_proxy": self.http_proxy, + "use_cloud_org_for_api_access": None, }, ) @@ -271,6 +276,7 @@ def test_get_client_kwargs_custom_endpoint(self): "logging_config": None, "linked_customer_id": None, "http_proxy": None, + "use_cloud_org_for_api_access": None, }, ) @@ -306,6 +312,7 @@ def test_load_from_env(self): linked_customer_id=None, version=None, http_proxy=None, + use_cloud_org_for_api_access=None, ) def test_load_from_env_versioned(self): @@ -340,6 +347,7 @@ def test_load_from_env_versioned(self): linked_customer_id=None, version="v4", http_proxy=None, + use_cloud_org_for_api_access=None, ) def test_load_from_dict(self): @@ -372,6 +380,7 @@ def test_load_from_dict(self): linked_customer_id=None, version=None, http_proxy=None, + use_cloud_org_for_api_access=None, ) def test_load_from_dict_versioned(self): @@ -404,6 +413,7 @@ def test_load_from_dict_versioned(self): linked_customer_id=None, version="v4", http_proxy=None, + use_cloud_org_for_api_access=None, ) def test_load_from_string(self): @@ -436,6 +446,7 @@ def test_load_from_string(self): linked_customer_id=None, version=None, http_proxy=None, + use_cloud_org_for_api_access=None, ) def test_load_from_string_versioned(self): @@ -470,6 +481,7 @@ def test_load_from_string_versioned(self): linked_customer_id=None, version="v4", http_proxy=None, + use_cloud_org_for_api_access=None, ) def test_load_from_storage(self): @@ -510,6 +522,7 @@ def test_load_from_storage(self): linked_customer_id=None, version=None, http_proxy=None, + use_cloud_org_for_api_access=None, ) def test_load_from_storage_versioned(self): @@ -550,6 +563,7 @@ def test_load_from_storage_versioned(self): linked_customer_id=None, version="v4", http_proxy=None, + use_cloud_org_for_api_access=None, ) def test_load_from_storage_login_cid_int(self): @@ -592,6 +606,7 @@ def test_load_from_storage_login_cid_int(self): linked_customer_id=None, version=None, http_proxy=None, + use_cloud_org_for_api_access=None, ) def test_load_from_storage_custom_path(self): @@ -626,6 +641,7 @@ def test_load_from_storage_custom_path(self): linked_customer_id=None, version=None, http_proxy=None, + use_cloud_org_for_api_access=None, ) def test_load_from_storage_file_not_found(self): @@ -687,29 +703,7 @@ def test_load_from_storage_service_account_config(self): linked_customer_id=None, version=latest_version, http_proxy=None, - ) - - def test_load_from_storage_service_account_no_impersonated_email(self): - config = { - **self.default_config, - **{ - "json_key_file_path": self.json_key_file_path, - }, - } - - file_path = os.path.join(os.path.expanduser("~"), "google-ads.yaml") - self.fs.create_file(file_path, contents=yaml.safe_dump(config)) - mock_credentials_instance = mock.Mock() - - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ), mock.patch.object( - Client.oauth2, - "get_service_account_credentials", - return_value=mock_credentials_instance, - ): - self.assertRaises( - ValueError, Client.GoogleAdsClient.load_from_storage + use_cloud_org_for_api_access=None, ) def test_get_service(self): @@ -1068,6 +1062,7 @@ def test_load_http_proxy_from_env(self): linked_customer_id=None, version=None, http_proxy=self.http_proxy, + use_cloud_org_for_api_access=None, ) def test_load_http_proxy_from_dict(self): @@ -1101,6 +1096,7 @@ def test_load_http_proxy_from_dict(self): linked_customer_id=None, version=None, http_proxy=self.http_proxy, + use_cloud_org_for_api_access=None, ) def test_load_http_proxy_from_string(self): @@ -1134,6 +1130,7 @@ def test_load_http_proxy_from_string(self): linked_customer_id=None, version=None, http_proxy=self.http_proxy, + use_cloud_org_for_api_access=None, ) def test_load_http_proxy_from_storage(self): @@ -1175,4 +1172,5 @@ def test_load_http_proxy_from_storage(self): linked_customer_id=None, version=None, http_proxy=self.http_proxy, + use_cloud_org_for_api_access=None, ) diff --git a/tests/config_test.py b/tests/config_test.py index 56ee5827b..1a685cce0 100644 --- a/tests/config_test.py +++ b/tests/config_test.py @@ -37,6 +37,7 @@ def setUp(self): self.configuration_file_path = "/usr/test/path/google-ads.yaml" self.impersonated_email = "impersonated@account.com" self.use_proto_plus = False + self.use_cloud_org_for_api_access = False # The below fields are defaults that include required keys. # They are merged with other keys in individual tests, and isolated # here so that new required keys don't need to be added to each test. @@ -602,10 +603,10 @@ def test_get_oauth2_installed_app_keys(self): config._OAUTH2_INSTALLED_APP_KEYS, ) - def test_get_oauth2_service_account_keys(self): + def test_get_oauth2_required_service_account_keys(self): self.assertEqual( - config.get_oauth2_service_account_keys(), - config._OAUTH2_SERVICE_ACCOUNT_KEYS, + config.get_oauth2_required_service_account_keys(), + config._OAUTH2_REQUIRED_SERVICE_ACCOUNT_KEYS, ) def test_convert_login_customer_id_to_str_with_int(self): @@ -659,3 +660,32 @@ def test_disambiguate_string_bool_raises_value_error(self): def test_disambiguate_string_bool_raises_type_error(self): self.assertRaises(TypeError, config.disambiguate_string_bool, {}) + + def test_load_from_env_use_cloud_org_for_api_access(self): + """Should load api access flag from environment when specified""" + environ = { + **self.default_env_var_config, + **{ + "GOOGLE_ADS_USE_CLOUD_ORG_FOR_API_ACCESS": self.use_cloud_org_for_api_access, + }, + } + + with mock.patch("os.environ", environ): + results = config.load_from_env() + self.assertEqual( + results["use_cloud_org_for_api_access"], + self.use_cloud_org_for_api_access, + ) + + def test_load_from_yaml_file_use_cloud_org_for_api_access(self): + """Should load "use_cloud_org_for_api_access" config from a yaml.""" + self._create_mock_yaml({"use_cloud_org_for_api_access": True}) + + result = config.load_from_yaml_file() + self.assertEqual(result["use_cloud_org_for_api_access"], True) + + def test_load_from_yaml_file_use_cloud_org_for_api_access_not_set(self): + """Should set "use_cloud_org_for_api_access" as None when not set.""" + self._create_mock_yaml({}) + result = config.load_from_yaml_file() + self.assertEqual(result.get("use_cloud_org_for_api_access"), None) diff --git a/tests/interceptors/logging_interceptor_test.py b/tests/interceptors/logging_interceptor_test.py index 212d759aa..961a7b0cc 100644 --- a/tests/interceptors/logging_interceptor_test.py +++ b/tests/interceptors/logging_interceptor_test.py @@ -53,6 +53,12 @@ ) change_event = import_module(f"{module_prefix}.resources.types.change_event") feed = import_module(f"{module_prefix}.resources.types.feed") +local_services_lead = import_module( + f"{module_prefix}.resources.types.local_services_lead" +) +local_services_lead_conversation = import_module( + f"{module_prefix}.resources.types.local_services_lead_conversation" +) class LoggingInterceptorTest(TestCase): @@ -891,3 +897,33 @@ def test_mask_customer_user_access_invitation_email(self): copy = mask_message(message, "REDACTED") self.assertIsInstance(copy, message.__class__) self.assertEqual(copy.email_address, "REDACTED") + + def test_mask_local_services_lead(self): + """Copies and masks a LocalServicesLead instance.""" + contact_details = local_services_lead.ContactDetails( + phone_number="800-555-0100", + email="dana@test.com", + consumer_name="Dana Test", + ) + message = local_services_lead.LocalServicesLead( + contact_details=contact_details + ) + copy = mask_message(message, "REDACTED") + self.assertIsInstance(copy, message.__class__) + self.assertEqual(copy.contact_details.email, "REDACTED") + self.assertEqual(copy.contact_details.phone_number, "REDACTED") + self.assertEqual(copy.contact_details.consumer_name, "REDACTED") + + def test_mask_local_services_lead_conversation(self): + """Copies and masks a LocalServicesLead instance.""" + message_details = local_services_lead_conversation.MessageDetails( + text="This is a test conversation", + ) + message = ( + local_services_lead_conversation.LocalServicesLeadConversation( + message_details=message_details + ) + ) + copy = mask_message(message, "REDACTED") + self.assertIsInstance(copy, message.__class__) + self.assertEqual(copy.message_details.text, "REDACTED") diff --git a/tests/interceptors/metadata_interceptor_test.py b/tests/interceptors/metadata_interceptor_test.py index df91bd1e6..e927ff5b8 100644 --- a/tests/interceptors/metadata_interceptor_test.py +++ b/tests/interceptors/metadata_interceptor_test.py @@ -31,6 +31,7 @@ def setUp(self): self.mock_developer_token = "1234567890" self.mock_login_customer_id = "0987654321" self.mock_linked_customer_id = "5555555555" + self.use_cloud_org_for_api_access = True self.python_version = python_version super(MetadataInterceptorTest, self).setUp() @@ -171,13 +172,10 @@ def test_intercept_updates_user_agent_add_pb(self): mock_client_call_details.method = "test/method" mock_client_call_details.timeout = 5 mock_client_call_details.metadata = [ - ( - "apples", - "oranges" - ), + ("apples", "oranges"), ( "x-goog-api-client", - f"gl-python/{self.python_version} grpc/1.45.0 gax/2.2.2" + f"gl-python/{self.python_version} grpc/1.45.0 gax/2.2.2", ), ] # Create a simple function that just returns the client_call_details @@ -241,3 +239,39 @@ def mock_continuation(client_call_details, request): # We assert that the _intercept method did not add the "pb" key # value pair because it was already present when passed in. self.assertEqual(user_agent.count("pb"), 1) + + def test_intercept_unary_stream_use_cloud_org_for_api_access(self): + interceptor = MetadataInterceptor( + self.mock_developer_token, + self.mock_login_customer_id, + self.mock_linked_customer_id, + self.use_cloud_org_for_api_access, + ) + + mock_continuation = mock.Mock(return_value=None) + mock_client_call_details = mock.Mock() + mock_client_call_details.method = "test/method" + mock_client_call_details.timeout = 5 + mock_client_call_details.metadata = [("apples", "oranges")] + mock_request = mock.Mock() + + with mock.patch.object( + interceptor, + "_update_client_call_details_metadata", + wraps=interceptor._update_client_call_details_metadata, + ) as mock_updater: + interceptor.intercept_unary_stream( + mock_continuation, mock_client_call_details, mock_request + ) + # Assets that if "use_cloud_org_for_api_access" is passed into + # MetadataInterceptor as True, then + mock_updater.assert_called_once_with( + mock_client_call_details, + [ + mock_client_call_details.metadata[0], + interceptor.login_customer_id_meta, + interceptor.linked_customer_id_meta, + ], + ) + + mock_continuation.assert_called_once()