diff --git a/ChangeLog b/ChangeLog index 5c277801f..8f2edcc41 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +* 30.0.0 +- Google Ads API v23_2 release. +- Fix config module so that login_customer_id=None doesn't raise an error. +- Rename "gaada" configuration setting to "ads_assistant" +- Set default for brand_guidelines_enabled to True in Pmax examples. +- Fix a small bug in setting the video upload resource name + * 29.2.0 - Google Ads API v23_1 release. - Update Google Ads API v20, v21, and v22 to include EU political advertising changes. diff --git a/google/ads/googleads/__init__.py b/google/ads/googleads/__init__.py index 675d2512d..0fea461fb 100644 --- a/google/ads/googleads/__init__.py +++ b/google/ads/googleads/__init__.py @@ -19,7 +19,7 @@ import google.ads.googleads.errors import google.ads.googleads.util -VERSION = "29.2.0" +VERSION = "30.0.0" # Checks if the current runtime is Python 3.9. if sys.version_info.major == 3 and sys.version_info.minor <= 9: diff --git a/google/ads/googleads/v23/__init__.py b/google/ads/googleads/v23/__init__.py index 0a324f8ad..c84c64447 100644 --- a/google/ads/googleads/v23/__init__.py +++ b/google/ads/googleads/v23/__init__.py @@ -27,6 +27,7 @@ # this code path once we drop support for Python 3.7 import importlib_metadata as metadata +from . import actions from . import common from . import enums from . import errors @@ -131,6 +132,7 @@ def _get_version(dependency_name): ) __all__ = ( + "actions", "common", "enums", "errors", diff --git a/google/ads/googleads/v23/actions/__init__.py b/google/ads/googleads/v23/actions/__init__.py new file mode 100644 index 000000000..fbdb2019a --- /dev/null +++ b/google/ads/googleads/v23/actions/__init__.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from google.ads.googleads.v23 import gapic_version as package_version + +import google.api_core as api_core +import sys + +__version__ = package_version.__version__ + +if sys.version_info >= (3, 8): # pragma: NO COVER + from importlib import metadata +else: # pragma: NO COVER + # TODO(https://github.com/googleapis/python-api-core/issues/835): Remove + # this code path once we drop support for Python 3.7 + import importlib_metadata as metadata + + +from .types.book_campaigns import BookCampaignsOperation +from .types.book_campaigns import BookCampaignsResult +from .types.quote_campaigns import QuoteCampaignsOperation +from .types.quote_campaigns import QuoteCampaignsResult + +if hasattr(api_core, "check_python_version") and hasattr( + api_core, "check_dependency_versions" +): # pragma: NO COVER + api_core.check_python_version("google.ads.googleads.v23") # type: ignore + api_core.check_dependency_versions("google.ads.googleads.v23") # type: ignore +else: # pragma: NO COVER + # An older version of api_core is installed which does not define the + # functions above. We do equivalent checks manually. + try: + import warnings + import sys + + _py_version_str = sys.version.split()[0] + _package_label = "google.ads.googleads.v23" + if sys.version_info < (3, 9): + warnings.warn( + "You are using a non-supported Python version " + + f"({_py_version_str}). Google will not post any further " + + f"updates to {_package_label} supporting this Python version. " + + "Please upgrade to the latest Python version, or at " + + f"least to Python 3.9, and then update {_package_label}.", + FutureWarning, + ) + if sys.version_info[:2] == (3, 9): + warnings.warn( + f"You are using a Python version ({_py_version_str}) " + + f"which Google will stop supporting in {_package_label} in " + + "January 2026. Please " + + "upgrade to the latest Python version, or at " + + "least to Python 3.10, before then, and " + + f"then update {_package_label}.", + FutureWarning, + ) + + def parse_version_to_tuple(version_string: str): + """Safely converts a semantic version string to a comparable tuple of integers. + Example: "4.25.8" -> (4, 25, 8) + Ignores non-numeric parts and handles common version formats. + Args: + version_string: Version string in the format "x.y.z" or "x.y.z" + Returns: + Tuple of integers for the parsed version string. + """ + parts = [] + for part in version_string.split("."): + try: + parts.append(int(part)) + except ValueError: + # If it's a non-numeric part (e.g., '1.0.0b1' -> 'b1'), stop here. + # This is a simplification compared to 'packaging.parse_version', but sufficient + # for comparing strictly numeric semantic versions. + break + return tuple(parts) + + def _get_version(dependency_name): + try: + version_string: str = metadata.version(dependency_name) + parsed_version = parse_version_to_tuple(version_string) + return (parsed_version, version_string) + except Exception: + # Catch exceptions from metadata.version() (e.g., PackageNotFoundError) + # or errors during parse_version_to_tuple + return (None, "--") + + _dependency_package = "google.protobuf" + _next_supported_version = "4.25.8" + _next_supported_version_tuple = (4, 25, 8) + _recommendation = " (we recommend 6.x)" + (_version_used, _version_used_string) = _get_version( + _dependency_package + ) + if _version_used and _version_used < _next_supported_version_tuple: + warnings.warn( + f"Package {_package_label} depends on " + + f"{_dependency_package}, currently installed at version " + + f"{_version_used_string}. Future updates to " + + f"{_package_label} will require {_dependency_package} at " + + f"version {_next_supported_version} or higher{_recommendation}." + + " Please ensure " + + "that either (a) your Python environment doesn't pin the " + + f"version of {_dependency_package}, so that updates to " + + f"{_package_label} can require the higher version, or " + + "(b) you manually update your Python environment to use at " + + f"least version {_next_supported_version} of " + + f"{_dependency_package}.", + FutureWarning, + ) + except Exception: + warnings.warn( + "Could not determine the version of Python " + + "currently being used. To continue receiving " + + "updates for {_package_label}, ensure you are " + + "using a supported version of Python; see " + + "https://devguide.python.org/versions/" + ) + +__all__ = ( + "BookCampaignsOperation", + "BookCampaignsResult", + "QuoteCampaignsOperation", + "QuoteCampaignsResult", +) diff --git a/google/ads/googleads/v23/actions/services/__init__.py b/google/ads/googleads/v23/actions/services/__init__.py new file mode 100644 index 000000000..cbf94b283 --- /dev/null +++ b/google/ads/googleads/v23/actions/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/google/ads/googleads/v23/actions/types/__init__.py b/google/ads/googleads/v23/actions/types/__init__.py new file mode 100644 index 000000000..68ffb7cd9 --- /dev/null +++ b/google/ads/googleads/v23/actions/types/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from .book_campaigns import ( + BookCampaignsOperation, + BookCampaignsResult, +) +from .quote_campaigns import ( + QuoteCampaignsOperation, + QuoteCampaignsResult, +) + +__all__ = ( + "BookCampaignsOperation", + "BookCampaignsResult", + "QuoteCampaignsOperation", + "QuoteCampaignsResult", +) diff --git a/google/ads/googleads/v23/actions/types/book_campaigns.py b/google/ads/googleads/v23/actions/types/book_campaigns.py new file mode 100644 index 000000000..957af9d9d --- /dev/null +++ b/google/ads/googleads/v23/actions/types/book_campaigns.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v23.enums.types import reservation_request_type + + +__protobuf__ = proto.module( + package="google.ads.googleads.v23.actions", + marshal="google.ads.googleads.v23", + manifest={ + "BookCampaignsOperation", + "BookCampaignsResult", + }, +) + + +class BookCampaignsOperation(proto.Message): + r"""Request message for the BookCampaigns action. + Request including this operation can have a latency of up to 30 + seconds. This feature is not publicly available. + + Attributes: + campaigns (MutableSequence[google.ads.googleads.v23.actions.types.BookCampaignsOperation.Campaign]): + Campaigns to book. Maximum 2 campaigns per + request. + quote_signature (str): + If provided, the signature of the previous + quote. Clients should always provide the quote + signature from previous quotes if they haven't + changed the campaigns to prevent price + fluctuations within a user session. + """ + + class Campaign(proto.Message): + r"""A single campaign to book. + + Attributes: + campaign (str): + Campaign resource to book. Format: + customers/{customer_id}/campaigns/{campaign_id} + request_type (google.ads.googleads.v23.enums.types.ReservationRequestTypeEnum.ReservationRequestType): + Determines if the current request should book + the inventory or hold it. + """ + + campaign: str = proto.Field( + proto.STRING, + number=1, + ) + request_type: ( + reservation_request_type.ReservationRequestTypeEnum.ReservationRequestType + ) = proto.Field( + proto.ENUM, + number=2, + enum=reservation_request_type.ReservationRequestTypeEnum.ReservationRequestType, + ) + + campaigns: MutableSequence[Campaign] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=Campaign, + ) + quote_signature: str = proto.Field( + proto.STRING, + number=2, + ) + + +class BookCampaignsResult(proto.Message): + r"""Response message for the BookCampaigns action. Note that if the + response contains errors, the action response will not be returned, + but a quote may still be returned in the + ErrorDetails.reservation_error_details field. + + """ + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/actions/types/quote_campaigns.py b/google/ads/googleads/v23/actions/types/quote_campaigns.py new file mode 100644 index 000000000..49e76e898 --- /dev/null +++ b/google/ads/googleads/v23/actions/types/quote_campaigns.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v23.common.types import campaign_reservation_quote + + +__protobuf__ = proto.module( + package="google.ads.googleads.v23.actions", + marshal="google.ads.googleads.v23", + manifest={ + "QuoteCampaignsOperation", + "QuoteCampaignsResult", + }, +) + + +class QuoteCampaignsOperation(proto.Message): + r"""Request message for the QuoteCampaigns action. + Request including this operation can have a latency of up to 30 + seconds. This feature is not publicly available. + + Attributes: + campaigns (MutableSequence[google.ads.googleads.v23.actions.types.QuoteCampaignsOperation.Campaign]): + Campaigns for which the quotes are requested. + Maximum 2 campaigns per request. + quote_signature (str): + If provided, the signature of the previous + quote. Clients should always provide the quote + signature from previous quotes if they haven't + changed the campaigns to prevent price + fluctuations within a user session. + """ + + class Campaign(proto.Message): + r"""A campaign for which the quote is requested. + + Attributes: + campaign (str): + Campaign for which the quote is requested. Format: + customers/{customer_id}/campaigns/{campaign_id} + """ + + campaign: str = proto.Field( + proto.STRING, + number=1, + ) + + campaigns: MutableSequence[Campaign] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=Campaign, + ) + quote_signature: str = proto.Field( + proto.STRING, + number=2, + ) + + +class QuoteCampaignsResult(proto.Message): + r"""The response of the QuoteCampaigns action, when the action is + successful. Note that if the response contains errors, the action + response will not be returned, but a quote may still be returned in + the ErrorDetails.reservation_error_details field. + + Attributes: + quotes (MutableSequence[google.ads.googleads.v23.common.types.CampaignReservationQuote]): + The quotes for the requested campaigns. + quote_signature (str): + The signature of the quote. This signature + should be used when booking the quote. + """ + + quotes: MutableSequence[ + campaign_reservation_quote.CampaignReservationQuote + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=campaign_reservation_quote.CampaignReservationQuote, + ) + quote_signature: str = proto.Field( + proto.STRING, + number=2, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/common/__init__.py b/google/ads/googleads/v23/common/__init__.py index 3da3bcf8c..530eb01a6 100644 --- a/google/ads/googleads/v23/common/__init__.py +++ b/google/ads/googleads/v23/common/__init__.py @@ -137,6 +137,7 @@ from .types.audience_insights_attribute import AudienceInsightsCategory from .types.audience_insights_attribute import AudienceInsightsEntity from .types.audience_insights_attribute import AudienceInsightsLineup +from .types.audience_insights_attribute import InsightsAudienceAttributeGroup from .types.audience_insights_attribute import KnowledgeGraphAttributeMetadata from .types.audience_insights_attribute import LineupAttributeMetadata from .types.audience_insights_attribute import LocationAttributeMetadata @@ -179,6 +180,7 @@ from .types.bidding import TargetRoas from .types.bidding import TargetSpend from .types.campaign_goal_settings import CampaignGoalSettings +from .types.campaign_reservation_quote import CampaignReservationQuote from .types.click_location import ClickLocation from .types.consent import Consent from .types.criteria import ActivityCityInfo @@ -552,6 +554,7 @@ def _get_version(dependency_name): "CalloutAsset", "CalloutFeedItem", "CampaignGoalSettings", + "CampaignReservationQuote", "CampaignThirdPartyBrandLiftIntegrationPartner", "CampaignThirdPartyBrandSafetyIntegrationPartner", "CampaignThirdPartyIntegrationPartners", @@ -645,6 +648,7 @@ def _get_version(dependency_name): "ImageDimension", "InFeedVideoAdInfo", "IncomeRangeInfo", + "InsightsAudienceAttributeGroup", "InteractionTypeInfo", "IpBlockInfo", "ItemAttribute", diff --git a/google/ads/googleads/v23/common/types/__init__.py b/google/ads/googleads/v23/common/types/__init__.py index 206150e93..bf0c22813 100644 --- a/google/ads/googleads/v23/common/types/__init__.py +++ b/google/ads/googleads/v23/common/types/__init__.py @@ -135,6 +135,7 @@ AudienceInsightsCategory, AudienceInsightsEntity, AudienceInsightsLineup, + InsightsAudienceAttributeGroup, KnowledgeGraphAttributeMetadata, LineupAttributeMetadata, LocationAttributeMetadata, @@ -184,6 +185,9 @@ from .campaign_goal_settings import ( CampaignGoalSettings, ) +from .campaign_reservation_quote import ( + CampaignReservationQuote, +) from .click_location import ( ClickLocation, ) @@ -543,6 +547,7 @@ "AudienceInsightsCategory", "AudienceInsightsEntity", "AudienceInsightsLineup", + "InsightsAudienceAttributeGroup", "KnowledgeGraphAttributeMetadata", "LineupAttributeMetadata", "LocationAttributeMetadata", @@ -585,6 +590,7 @@ "TargetRoas", "TargetSpend", "CampaignGoalSettings", + "CampaignReservationQuote", "ClickLocation", "Consent", "ActivityCityInfo", diff --git a/google/ads/googleads/v23/common/types/audience_insights_attribute.py b/google/ads/googleads/v23/common/types/audience_insights_attribute.py index b1a29d6d0..8e3cd1f58 100644 --- a/google/ads/googleads/v23/common/types/audience_insights_attribute.py +++ b/google/ads/googleads/v23/common/types/audience_insights_attribute.py @@ -47,6 +47,7 @@ "KnowledgeGraphAttributeMetadata", "UserListAttributeMetadata", "AudienceInsightsAttributeMetadataGroup", + "InsightsAudienceAttributeGroup", }, ) @@ -651,4 +652,25 @@ class AudienceInsightsAttributeMetadataGroup(proto.Message): ) +class InsightsAudienceAttributeGroup(proto.Message): + r"""A list of AudienceInsightsAttributes. + + Attributes: + attributes (MutableSequence[google.ads.googleads.v23.common.types.AudienceInsightsAttribute]): + Required. A collection of audience attributes + combined with logical OR. Attributes need not + all be the same dimension. Only Knowledge Graph + entities, Product & Service Categories, and user + interests are supported in this context. + """ + + attributes: MutableSequence["AudienceInsightsAttribute"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="AudienceInsightsAttribute", + ) + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/common/types/campaign_reservation_quote.py b/google/ads/googleads/v23/common/types/campaign_reservation_quote.py new file mode 100644 index 000000000..bad428c8f --- /dev/null +++ b/google/ads/googleads/v23/common/types/campaign_reservation_quote.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v23.common", + marshal="google.ads.googleads.v23", + manifest={ + "CampaignReservationQuote", + }, +) + + +class CampaignReservationQuote(proto.Message): + r"""The campaign reservation quote. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + campaign (str): + The campaign resource name, as it was specified in the + request. It could contain a temp ID. Format: + customers/{customer_id}/campaigns/{campaign_id} + max_budget_micros (int): + Maximum budget to get all available + impressions at the current CPM. Capped at 10M + USD. Specified in micros of the advertiser + currency. + possible_hold_duration_seconds (int): + The possible duration of the hold, in + seconds. + suggested_cpm_micros (int): + The CPM that would be accepted for the + campaign calculated at the proposed budget. + Specified in micros of the advertiser currency. + + This field is a member of `oneof`_ ``suggested_quote``. + """ + + campaign: str = proto.Field( + proto.STRING, + number=1, + ) + max_budget_micros: int = proto.Field( + proto.INT64, + number=3, + ) + possible_hold_duration_seconds: int = proto.Field( + proto.INT64, + number=4, + ) + suggested_cpm_micros: int = proto.Field( + proto.INT64, + number=2, + oneof="suggested_quote", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/common/types/metrics.py b/google/ads/googleads/v23/common/types/metrics.py index bfd700e83..fb863b850 100644 --- a/google/ads/googleads/v23/common/types/metrics.py +++ b/google/ads/googleads/v23/common/types/metrics.py @@ -1885,6 +1885,12 @@ class Metrics(proto.Message): measurable for audibility. This field is a member of `oneof`_ ``_active_view_audible_quartile_p100_rate``. + biddable_indirect_install_first_in_app_conversion_micros (int): + The number of biddable first in app + conversions where the app install was driven by + interaction with a web campaign. + + This field is a member of `oneof`_ ``_biddable_indirect_install_first_in_app_conversion_micros``. """ absolute_top_impression_percentage: float = proto.Field( @@ -3083,6 +3089,11 @@ class Metrics(proto.Message): number=425, optional=True, ) + biddable_indirect_install_first_in_app_conversion_micros: int = proto.Field( + proto.INT64, + number=426, + optional=True, + ) class SearchVolumeRange(proto.Message): diff --git a/google/ads/googleads/v23/enums/__init__.py b/google/ads/googleads/v23/enums/__init__.py index f9b7cb39d..fc350f334 100644 --- a/google/ads/googleads/v23/enums/__init__.py +++ b/google/ads/googleads/v23/enums/__init__.py @@ -427,6 +427,7 @@ ) from .types.optimization_goal_type import OptimizationGoalTypeEnum from .types.parental_status_type import ParentalStatusTypeEnum +from .types.partnership_opportunity import PartnershipOpportunityEnum from .types.payment_mode import PaymentModeEnum from .types.performance_max_upgrade_status import ( PerformanceMaxUpgradeStatusEnum, @@ -445,6 +446,7 @@ PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum, ) from .types.positive_geo_target_type import PositiveGeoTargetTypeEnum +from .types.preview_type import PreviewTypeEnum from .types.price_extension_price_qualifier import ( PriceExtensionPriceQualifierEnum, ) @@ -486,6 +488,7 @@ ) from .types.recommendation_type import RecommendationTypeEnum from .types.regulatory_fee_type import RegulatoryFeeTypeEnum +from .types.reservation_request_type import ReservationRequestTypeEnum from .types.resource_change_operation import ResourceChangeOperationEnum from .types.resource_limit_type import ResourceLimitTypeEnum from .types.response_content_type import ResponseContentTypeEnum @@ -597,6 +600,7 @@ from .types.video_ad_sequence_minimum_duration import ( VideoAdSequenceMinimumDurationEnum, ) +from .types.video_enhancement_source import VideoEnhancementSourceEnum from .types.video_thumbnail import VideoThumbnailEnum from .types.webpage_condition_operand import WebpageConditionOperandEnum from .types.webpage_condition_operator import WebpageConditionOperatorEnum @@ -958,6 +962,7 @@ def _get_version(dependency_name): "OperatingSystemVersionOperatorTypeEnum", "OptimizationGoalTypeEnum", "ParentalStatusTypeEnum", + "PartnershipOpportunityEnum", "PaymentModeEnum", "PerformanceMaxUpgradeStatusEnum", "PlacementTypeEnum", @@ -968,6 +973,7 @@ def _get_version(dependency_name): "PolicyTopicEvidenceDestinationNotWorkingDeviceEnum", "PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum", "PositiveGeoTargetTypeEnum", + "PreviewTypeEnum", "PriceExtensionPriceQualifierEnum", "PriceExtensionPriceUnitEnum", "PriceExtensionTypeEnum", @@ -995,6 +1001,7 @@ def _get_version(dependency_name): "RecommendationSubscriptionStatusEnum", "RecommendationTypeEnum", "RegulatoryFeeTypeEnum", + "ReservationRequestTypeEnum", "ResourceChangeOperationEnum", "ResourceLimitTypeEnum", "ResponseContentTypeEnum", @@ -1060,6 +1067,7 @@ def _get_version(dependency_name): "VideoAdFormatRestrictionEnum", "VideoAdSequenceInteractionTypeEnum", "VideoAdSequenceMinimumDurationEnum", + "VideoEnhancementSourceEnum", "VideoThumbnailEnum", "WebpageConditionOperandEnum", "WebpageConditionOperatorEnum", diff --git a/google/ads/googleads/v23/enums/types/__init__.py b/google/ads/googleads/v23/enums/types/__init__.py index 3aaafeebc..d705af761 100644 --- a/google/ads/googleads/v23/enums/types/__init__.py +++ b/google/ads/googleads/v23/enums/types/__init__.py @@ -784,6 +784,9 @@ from .parental_status_type import ( ParentalStatusTypeEnum, ) +from .partnership_opportunity import ( + PartnershipOpportunityEnum, +) from .payment_mode import ( PaymentModeEnum, ) @@ -814,6 +817,9 @@ from .positive_geo_target_type import ( PositiveGeoTargetTypeEnum, ) +from .preview_type import ( + PreviewTypeEnum, +) from .price_extension_price_qualifier import ( PriceExtensionPriceQualifierEnum, ) @@ -895,6 +901,9 @@ from .regulatory_fee_type import ( RegulatoryFeeTypeEnum, ) +from .reservation_request_type import ( + ReservationRequestTypeEnum, +) from .resource_change_operation import ( ResourceChangeOperationEnum, ) @@ -1090,6 +1099,9 @@ from .video_ad_sequence_minimum_duration import ( VideoAdSequenceMinimumDurationEnum, ) +from .video_enhancement_source import ( + VideoEnhancementSourceEnum, +) from .video_thumbnail import ( VideoThumbnailEnum, ) @@ -1367,6 +1379,7 @@ "OperatingSystemVersionOperatorTypeEnum", "OptimizationGoalTypeEnum", "ParentalStatusTypeEnum", + "PartnershipOpportunityEnum", "PaymentModeEnum", "PerformanceMaxUpgradeStatusEnum", "PlacementTypeEnum", @@ -1377,6 +1390,7 @@ "PolicyTopicEvidenceDestinationNotWorkingDeviceEnum", "PolicyTopicEvidenceDestinationNotWorkingDnsErrorTypeEnum", "PositiveGeoTargetTypeEnum", + "PreviewTypeEnum", "PriceExtensionPriceQualifierEnum", "PriceExtensionPriceUnitEnum", "PriceExtensionTypeEnum", @@ -1404,6 +1418,7 @@ "RecommendationSubscriptionStatusEnum", "RecommendationTypeEnum", "RegulatoryFeeTypeEnum", + "ReservationRequestTypeEnum", "ResourceChangeOperationEnum", "ResourceLimitTypeEnum", "ResponseContentTypeEnum", @@ -1469,6 +1484,7 @@ "VideoAdFormatRestrictionEnum", "VideoAdSequenceInteractionTypeEnum", "VideoAdSequenceMinimumDurationEnum", + "VideoEnhancementSourceEnum", "VideoThumbnailEnum", "WebpageConditionOperandEnum", "WebpageConditionOperatorEnum", diff --git a/google/ads/googleads/v23/enums/types/partnership_opportunity.py b/google/ads/googleads/v23/enums/types/partnership_opportunity.py new file mode 100644 index 000000000..813c54c0f --- /dev/null +++ b/google/ads/googleads/v23/enums/types/partnership_opportunity.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v23.enums", + marshal="google.ads.googleads.v23", + manifest={ + "PartnershipOpportunityEnum", + }, +) + + +class PartnershipOpportunityEnum(proto.Message): + r"""Container for enum describing partnership opportunity.""" + + class PartnershipOpportunity(proto.Enum): + r"""Partnership opportunity between media buyers and creators for + paid media on YouTube. + + Values: + UNSPECIFIED (0): + Default value. This value is equivalent to + null. + UNKNOWN (1): + Output-only. Represents a format not yet + defined in this enum. + CREATOR_PARTNERSHIPS (2): + A partnership opportunity that allows + advertisers to partner with YouTube creators on + sponsored content that mentions a brand or + product. See + https://support.google.com/google-ads/answer/15471603 + to learn more. + CREATOR_TAKEOVER (3): + A partnership opportunity that gives brands + exclusive access to all ad slots on channels of + top creators. + PARTNERSHIP_ADS (4): + A partnership opportunity that enables brands + to use YouTube creator videos in their ad + campaigns. See + https://support.google.com/google-ads/answer/15223349 + to learn more. + YOUTUBE_SELECT_LINEUPS (5): + A partnership opportunity that allows + advertisers to buy specific ad placements on a + reservation basis to target among the top 1% of + popular channels on YouTube. See + https://support.google.com/google-ads/answer/6030919 + to learn more. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + CREATOR_PARTNERSHIPS = 2 + CREATOR_TAKEOVER = 3 + PARTNERSHIP_ADS = 4 + YOUTUBE_SELECT_LINEUPS = 5 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/enums/types/preview_type.py b/google/ads/googleads/v23/enums/types/preview_type.py new file mode 100644 index 000000000..9e22c89a6 --- /dev/null +++ b/google/ads/googleads/v23/enums/types/preview_type.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v23.enums", + marshal="google.ads.googleads.v23", + manifest={ + "PreviewTypeEnum", + }, +) + + +class PreviewTypeEnum(proto.Message): + r"""Preview type.""" + + class PreviewType(proto.Enum): + r"""Enum describing the preview type. + Next Id: 4 + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + UI_PREVIEW (2): + Request a URL to a preview in the Google Ads + UI. The generated URLs are shareable. + YOUTUBE_LIVE_PREVIEW (3): + Request a URL to a preview of the ad in + YouTube. The generated URLs are shareable. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + UI_PREVIEW = 2 + YOUTUBE_LIVE_PREVIEW = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/enums/types/reach_plan_age_range.py b/google/ads/googleads/v23/enums/types/reach_plan_age_range.py index d0510b8aa..07a5aea2c 100644 --- a/google/ads/googleads/v23/enums/types/reach_plan_age_range.py +++ b/google/ads/googleads/v23/enums/types/reach_plan_age_range.py @@ -55,6 +55,16 @@ class ReachPlanAgeRange(proto.Enum): Between 18 and 65+ years old. AGE_RANGE_21_34 (8): Between 21 and 34 years old. + AGE_RANGE_21_44 (22): + Between 21 and 44 years old. + AGE_RANGE_21_49 (23): + Between 21 and 49 years old. + AGE_RANGE_21_54 (24): + Between 21 and 54 years old. + AGE_RANGE_21_64 (25): + Between 21 and 64 years old. + AGE_RANGE_21_65_UP (26): + Between 21 and 65+ years old. AGE_RANGE_25_34 (503002): Between 25 and 34 years old. AGE_RANGE_25_44 (9): @@ -103,6 +113,11 @@ class ReachPlanAgeRange(proto.Enum): AGE_RANGE_18_64 = 6 AGE_RANGE_18_65_UP = 7 AGE_RANGE_21_34 = 8 + AGE_RANGE_21_44 = 22 + AGE_RANGE_21_49 = 23 + AGE_RANGE_21_54 = 24 + AGE_RANGE_21_64 = 25 + AGE_RANGE_21_65_UP = 26 AGE_RANGE_25_34 = 503002 AGE_RANGE_25_44 = 9 AGE_RANGE_25_49 = 10 diff --git a/google/ads/googleads/v23/enums/types/reach_plan_surface.py b/google/ads/googleads/v23/enums/types/reach_plan_surface.py index fe20b262d..bbc65e369 100644 --- a/google/ads/googleads/v23/enums/types/reach_plan_surface.py +++ b/google/ads/googleads/v23/enums/types/reach_plan_surface.py @@ -59,6 +59,9 @@ class ReachPlanSurface(proto.Enum): Shorts ad surface. GOOGLE_DISPLAY_NETWORK (9): Google Display Network ad surface. + IN_STREAM_NON_SKIPPABLE_THIRTY_SECONDS (10): + In-Stream non-skippable (30 seconds) ad + surface. """ UNSPECIFIED = 0 @@ -71,6 +74,7 @@ class ReachPlanSurface(proto.Enum): IN_STREAM_SKIPPABLE = 5 SHORTS = 6 GOOGLE_DISPLAY_NETWORK = 9 + IN_STREAM_NON_SKIPPABLE_THIRTY_SECONDS = 10 __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/enums/types/reservation_request_type.py b/google/ads/googleads/v23/enums/types/reservation_request_type.py new file mode 100644 index 000000000..e8c7a3b42 --- /dev/null +++ b/google/ads/googleads/v23/enums/types/reservation_request_type.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v23.enums", + marshal="google.ads.googleads.v23", + manifest={ + "ReservationRequestTypeEnum", + }, +) + + +class ReservationRequestTypeEnum(proto.Message): + r"""Container for enum describing the request type of a + reservation booking. + + """ + + class ReservationRequestType(proto.Enum): + r"""Enum describing the request type of a reservation booking. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + BOOK (2): + Book the campaign. The campaign must have + ENABLED status. If the campaign has a hold, it + will remove the hold and confirm the contract. + HOLD (3): + Hold the inventory for the campaign. The + campaign must have PAUSED status to request a + hold. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + BOOK = 2 + HOLD = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/enums/types/video_enhancement_source.py b/google/ads/googleads/v23/enums/types/video_enhancement_source.py new file mode 100644 index 000000000..149d874e6 --- /dev/null +++ b/google/ads/googleads/v23/enums/types/video_enhancement_source.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v23.enums", + marshal="google.ads.googleads.v23", + manifest={ + "VideoEnhancementSourceEnum", + }, +) + + +class VideoEnhancementSourceEnum(proto.Message): + r"""Container for enum describing possible video enhancement + source types. + + """ + + class VideoEnhancementSource(proto.Enum): + r"""Enum listing the possible video sources. + + Values: + UNSPECIFIED (0): + Not specified. + UNKNOWN (1): + Used for return value only. Represents value + unknown in this version. + ADVERTISER (2): + The video is provided by the advertiser. + ENHANCED_BY_GOOGLE_ADS (3): + The video is an enhancement generated by + Google. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + ADVERTISER = 2 + ENHANCED_BY_GOOGLE_ADS = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/errors/__init__.py b/google/ads/googleads/v23/errors/__init__.py index 43577d19e..07470b1f8 100644 --- a/google/ads/googleads/v23/errors/__init__.py +++ b/google/ads/googleads/v23/errors/__init__.py @@ -31,6 +31,7 @@ from .types.access_invitation_error import AccessInvitationErrorEnum from .types.account_budget_proposal_error import AccountBudgetProposalErrorEnum from .types.account_link_error import AccountLinkErrorEnum +from .types.action_error import ActionErrorEnum from .types.ad_customizer_error import AdCustomizerErrorEnum from .types.ad_error import AdErrorEnum from .types.ad_group_ad_error import AdGroupAdErrorEnum @@ -89,6 +90,9 @@ from .types.change_status_error import ChangeStatusErrorEnum from .types.click_view_error import ClickViewErrorEnum from .types.collection_size_error import CollectionSizeErrorEnum +from .types.content_creator_insights_error import ( + ContentCreatorInsightsErrorEnum, +) from .types.context_error import ContextErrorEnum from .types.conversion_action_error import ConversionActionErrorEnum from .types.conversion_adjustment_upload_error import ( @@ -138,6 +142,7 @@ from .types.errors import PolicyFindingDetails from .types.errors import PolicyViolationDetails from .types.errors import QuotaErrorDetails +from .types.errors import ReservationErrorDetails from .types.errors import ResourceCountDetails from .types.experiment_arm_error import ExperimentArmErrorEnum from .types.experiment_error import ExperimentErrorEnum @@ -240,6 +245,7 @@ from .types.user_list_customer_type_error import UserListCustomerTypeErrorEnum from .types.user_list_error import UserListErrorEnum from .types.video_campaign_error import VideoCampaignErrorEnum +from .types.video_reservation_error import VideoReservationErrorEnum from .types.youtube_video_registration_error import ( YoutubeVideoRegistrationErrorEnum, ) @@ -344,6 +350,7 @@ def _get_version(dependency_name): "AccessInvitationErrorEnum", "AccountBudgetProposalErrorEnum", "AccountLinkErrorEnum", + "ActionErrorEnum", "AdCustomizerErrorEnum", "AdErrorEnum", "AdGroupAdErrorEnum", @@ -393,6 +400,7 @@ def _get_version(dependency_name): "ChangeStatusErrorEnum", "ClickViewErrorEnum", "CollectionSizeErrorEnum", + "ContentCreatorInsightsErrorEnum", "ContextErrorEnum", "ConversionActionErrorEnum", "ConversionAdjustmentUploadErrorEnum", @@ -495,6 +503,7 @@ def _get_version(dependency_name): "RecommendationSubscriptionErrorEnum", "RegionCodeErrorEnum", "RequestErrorEnum", + "ReservationErrorDetails", "ResourceAccessDeniedErrorEnum", "ResourceCountDetails", "ResourceCountLimitExceededErrorEnum", @@ -515,5 +524,6 @@ def _get_version(dependency_name): "UserListCustomerTypeErrorEnum", "UserListErrorEnum", "VideoCampaignErrorEnum", + "VideoReservationErrorEnum", "YoutubeVideoRegistrationErrorEnum", ) diff --git a/google/ads/googleads/v23/errors/types/__init__.py b/google/ads/googleads/v23/errors/types/__init__.py index 40c683a65..e43bfd04a 100644 --- a/google/ads/googleads/v23/errors/types/__init__.py +++ b/google/ads/googleads/v23/errors/types/__init__.py @@ -22,6 +22,9 @@ from .account_link_error import ( AccountLinkErrorEnum, ) +from .action_error import ( + ActionErrorEnum, +) from .ad_customizer_error import ( AdCustomizerErrorEnum, ) @@ -166,6 +169,9 @@ from .collection_size_error import ( CollectionSizeErrorEnum, ) +from .content_creator_insights_error import ( + ContentCreatorInsightsErrorEnum, +) from .context_error import ( ContextErrorEnum, ) @@ -266,6 +272,7 @@ PolicyFindingDetails, PolicyViolationDetails, QuotaErrorDetails, + ReservationErrorDetails, ResourceCountDetails, ) from .experiment_arm_error import ( @@ -517,6 +524,9 @@ from .video_campaign_error import ( VideoCampaignErrorEnum, ) +from .video_reservation_error import ( + VideoReservationErrorEnum, +) from .youtube_video_registration_error import ( YoutubeVideoRegistrationErrorEnum, ) @@ -525,6 +535,7 @@ "AccessInvitationErrorEnum", "AccountBudgetProposalErrorEnum", "AccountLinkErrorEnum", + "ActionErrorEnum", "AdCustomizerErrorEnum", "AdErrorEnum", "AdGroupAdErrorEnum", @@ -573,6 +584,7 @@ "ChangeStatusErrorEnum", "ClickViewErrorEnum", "CollectionSizeErrorEnum", + "ContentCreatorInsightsErrorEnum", "ContextErrorEnum", "ConversionActionErrorEnum", "ConversionAdjustmentUploadErrorEnum", @@ -612,6 +624,7 @@ "PolicyFindingDetails", "PolicyViolationDetails", "QuotaErrorDetails", + "ReservationErrorDetails", "ResourceCountDetails", "ExperimentArmErrorEnum", "ExperimentErrorEnum", @@ -696,5 +709,6 @@ "UserListCustomerTypeErrorEnum", "UserListErrorEnum", "VideoCampaignErrorEnum", + "VideoReservationErrorEnum", "YoutubeVideoRegistrationErrorEnum", ) diff --git a/google/ads/googleads/v23/errors/types/action_error.py b/google/ads/googleads/v23/errors/types/action_error.py new file mode 100644 index 000000000..79b020e73 --- /dev/null +++ b/google/ads/googleads/v23/errors/types/action_error.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v23.errors", + marshal="google.ads.googleads.v23", + manifest={ + "ActionErrorEnum", + }, +) + + +class ActionErrorEnum(proto.Message): + r"""Container for enum describing possible action errors.""" + + class ActionError(proto.Enum): + r"""Enum describing possible action errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + REQUIRED_FIELD_MISSING (2): + The action is missing a required field. + INVALID_ARGUMENT (3): + The action has invalid arguments in the + request. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + REQUIRED_FIELD_MISSING = 2 + INVALID_ARGUMENT = 3 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/errors/types/ad_group_ad_error.py b/google/ads/googleads/v23/errors/types/ad_group_ad_error.py index 7a31a6c94..1ab1d533d 100644 --- a/google/ads/googleads/v23/errors/types/ad_group_ad_error.py +++ b/google/ads/googleads/v23/errors/types/ad_group_ad_error.py @@ -72,6 +72,8 @@ class AdGroupAdError(proto.Enum): be updated. Only removals are permitted. AD_SHARING_NOT_ALLOWED (13): Ad sharing is not allowed. + DURATION_TOO_SHORT (14): + The duration of the AdGroupAd is too short. """ UNSPECIFIED = 0 @@ -88,6 +90,7 @@ class AdGroupAdError(proto.Enum): AD_TYPE_CANNOT_BE_REMOVED = 11 CANNOT_UPDATE_DEPRECATED_ADS = 12 AD_SHARING_NOT_ALLOWED = 13 + DURATION_TOO_SHORT = 14 __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/errors/types/asset_error.py b/google/ads/googleads/v23/errors/types/asset_error.py index 3dc198e6e..ff91cb4db 100644 --- a/google/ads/googleads/v23/errors/types/asset_error.py +++ b/google/ads/googleads/v23/errors/types/asset_error.py @@ -41,15 +41,15 @@ class AssetError(proto.Enum): The received error code is not known in this version. CUSTOMER_NOT_ON_ALLOWLIST_FOR_ASSET_TYPE (13): - The customer is not is not on the allow-list - for this asset type. + The customer is not on the allow-list for + this asset type. DUPLICATE_ASSET (3): Assets are duplicated across operations. DUPLICATE_ASSET_NAME (4): The asset name is duplicated, either across operations or with an existing asset. ASSET_DATA_IS_MISSING (5): - The Asset.asset_data oneof is empty. + The ``Asset.asset_data`` oneof is empty. CANNOT_MODIFY_ASSET_NAME (6): The asset has a name which is different from an existing duplicate that represents the same @@ -85,10 +85,10 @@ class AssetError(proto.Enum): specified. DUPLICATE_ASSETS_WITH_DIFFERENT_FIELD_VALUE (18): Duplicate assets across operations, which have identical - Asset.asset_data oneof, cannot have different asset level - fields for asset types which are deduped. + ``Asset.asset_data`` oneof, cannot have different asset + level fields for asset types which are deduped. CALL_CARRIER_SPECIFIC_SHORT_NUMBER_NOT_ALLOWED (19): - Carrier specific short number is not allowed. + Carrier-specific short number is not allowed. CALL_CUSTOMER_CONSENT_FOR_CALL_RECORDING_REQUIRED (20): Customer consent required for call recording Terms of Service. @@ -96,9 +96,9 @@ class AssetError(proto.Enum): The type of the specified phone number is not allowed. CALL_INVALID_CONVERSION_ACTION (22): - If the default call_conversion_action is not used, the - customer must have a ConversionAction with the same id and - the ConversionAction must be call conversion type. + If the default ``call_conversion_action`` is not used, the + customer must have a ``ConversionAction`` with the same id + and the ``ConversionAction`` must be call conversion type. CALL_INVALID_COUNTRY_CODE (23): The country code of the phone number is invalid. @@ -108,17 +108,17 @@ class AssetError(proto.Enum): The input phone number is not a valid phone number. CALL_PHONE_NUMBER_NOT_SUPPORTED_FOR_COUNTRY (26): - The phone number is not supported for + The phone number is not supported for this country. CALL_PREMIUM_RATE_NUMBER_NOT_ALLOWED (27): Premium rate phone number is not allowed. CALL_VANITY_PHONE_NUMBER_NOT_ALLOWED (28): Vanity phone number is not allowed. PRICE_HEADER_SAME_AS_DESCRIPTION (29): - PriceOffering cannot have the same value for - header and description. + ``PriceOffering`` cannot have the same value for header and + description. MOBILE_APP_INVALID_APP_ID (30): - AppId is invalid. + ``AppId`` is invalid. MOBILE_APP_INVALID_FINAL_URL_FOR_APP_DOWNLOAD_URL (31): Invalid App download URL in final URLs. NAME_REQUIRED_FOR_ASSET_TYPE (32): @@ -134,8 +134,7 @@ class AssetError(proto.Enum): User can not modify the automatically created asset. LEAD_FORM_LOCATION_ANSWER_TYPE_DISALLOWED (37): - Lead Form is disallowed to use "LOCATION" - answer type. + Lead Form is disallowed to use ``LOCATION`` answer type. PAGE_FEED_INVALID_LABEL_TEXT (38): Page Feed label text contains invalid characters. @@ -144,7 +143,7 @@ class AssetError(proto.Enum): whatsapp message asset type. CUSTOMER_NOT_ON_ALLOWLIST_FOR_APP_DEEP_LINK_ASSETS (40): Only customers on the allowlist can create - AppDeepLinkAsset. + ``AppDeepLinkAsset``. PROMOTION_BARCODE_CANNOT_CONTAIN_LINKS (41): Promotion barcode cannot contain links. PROMOTION_BARCODE_INVALID_FORMAT (42): diff --git a/google/ads/googleads/v23/errors/types/content_creator_insights_error.py b/google/ads/googleads/v23/errors/types/content_creator_insights_error.py new file mode 100644 index 000000000..0fdfa11be --- /dev/null +++ b/google/ads/googleads/v23/errors/types/content_creator_insights_error.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v23.errors", + marshal="google.ads.googleads.v23", + manifest={ + "ContentCreatorInsightsErrorEnum", + }, +) + + +class ContentCreatorInsightsErrorEnum(proto.Message): + r"""Container for enum describing possible errors returned from + the ContentCreatorInsightsService. + + """ + + class ContentCreatorInsightsError(proto.Enum): + r"""Enum describing possible errors from + ContentCreatorInsightsService. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + DIMENSION_INCOMPATIBLE_WITH_AUDIENCE_COMBINATIONS (2): + The dimension cannot be used in audience + combinations. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + DIMENSION_INCOMPATIBLE_WITH_AUDIENCE_COMBINATIONS = 2 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/errors/types/customer_client_link_error.py b/google/ads/googleads/v23/errors/types/customer_client_link_error.py index ba7229fa8..c7eff89fe 100644 --- a/google/ads/googleads/v23/errors/types/customer_client_link_error.py +++ b/google/ads/googleads/v23/errors/types/customer_client_link_error.py @@ -29,7 +29,7 @@ class CustomerClientLinkErrorEnum(proto.Message): - r"""Container for enum describing possible CustomeClientLink + r"""Container for enum describing possible CustomerClientLink errors. """ @@ -64,6 +64,12 @@ class CustomerClientLinkError(proto.Enum): of linked accounts. CLIENT_HAS_TOO_MANY_MANAGERS (9): Client has too many managers. + MAX_CUSTOMER_LIMIT_REACHED (10): + You have reached the maximum limit of + accounts that can be created for this account. + ACCOUNT_CREATION_POLICY_VIOLATION (11): + This account cannot create new client + accounts due to a Google Ads policy violation. """ UNSPECIFIED = 0 @@ -76,6 +82,8 @@ class CustomerClientLinkError(proto.Enum): CANNOT_HIDE_OR_UNHIDE_MANAGER_ACCOUNTS = 7 CUSTOMER_HAS_TOO_MANY_ACCOUNTS_AT_MANAGER = 8 CLIENT_HAS_TOO_MANY_MANAGERS = 9 + MAX_CUSTOMER_LIMIT_REACHED = 10 + ACCOUNT_CREATION_POLICY_VIOLATION = 11 __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/errors/types/errors.py b/google/ads/googleads/v23/errors/types/errors.py index d816e92c8..2edbbe36f 100644 --- a/google/ads/googleads/v23/errors/types/errors.py +++ b/google/ads/googleads/v23/errors/types/errors.py @@ -19,6 +19,7 @@ import proto # type: ignore +from google.ads.googleads.v23.common.types import campaign_reservation_quote from google.ads.googleads.v23.common.types import policy from google.ads.googleads.v23.common.types import value from google.ads.googleads.v23.enums.types import resource_limit_type @@ -31,6 +32,9 @@ from google.ads.googleads.v23.errors.types import ( account_link_error as gage_account_link_error, ) +from google.ads.googleads.v23.errors.types import ( + action_error as gage_action_error, +) from google.ads.googleads.v23.errors.types import ( ad_customizer_error as gage_ad_customizer_error, ) @@ -171,6 +175,9 @@ from google.ads.googleads.v23.errors.types import ( collection_size_error as gage_collection_size_error, ) +from google.ads.googleads.v23.errors.types import ( + content_creator_insights_error as gage_content_creator_insights_error, +) from google.ads.googleads.v23.errors.types import ( context_error as gage_context_error, ) @@ -498,6 +505,9 @@ from google.ads.googleads.v23.errors.types import ( video_campaign_error as gage_video_campaign_error, ) +from google.ads.googleads.v23.errors.types import ( + video_reservation_error as gage_video_reservation_error, +) from google.ads.googleads.v23.errors.types import ( youtube_video_registration_error as gage_youtube_video_registration_error, ) @@ -518,6 +528,7 @@ "QuotaErrorDetails", "ResourceCountDetails", "BudgetPerDayMinimumErrorDetails", + "ReservationErrorDetails", }, ) @@ -667,6 +678,10 @@ class ErrorCode(proto.Message): Indicates failure to properly authenticate user. + This field is a member of `oneof`_ ``error_code``. + action_error (google.ads.googleads.v23.errors.types.ActionErrorEnum.ActionError): + An error with a Tangle Action. + This field is a member of `oneof`_ ``error_code``. ad_group_criterion_customizer_error (google.ads.googleads.v23.errors.types.AdGroupCriterionCustomizerErrorEnum.AdGroupCriterionCustomizerError): The reasons for the ad group criterion @@ -1312,6 +1327,15 @@ class ErrorCode(proto.Message): incentive_error (google.ads.googleads.v23.errors.types.IncentiveErrorEnum.IncentiveError): The reasons for the incentive error + This field is a member of `oneof`_ ``error_code``. + content_creator_insights_error (google.ads.googleads.v23.errors.types.ContentCreatorInsightsErrorEnum.ContentCreatorInsightsError): + The reasons for the Content Creator Insights + error. + + This field is a member of `oneof`_ ``error_code``. + video_reservation_error (google.ads.googleads.v23.errors.types.VideoReservationErrorEnum.VideoReservationError): + The reasons for the video reservation error. + This field is a member of `oneof`_ ``error_code``. """ @@ -1435,6 +1459,12 @@ class ErrorCode(proto.Message): oneof="error_code", enum=gage_authentication_error.AuthenticationErrorEnum.AuthenticationError, ) + action_error: gage_action_error.ActionErrorEnum.ActionError = proto.Field( + proto.ENUM, + number=196, + oneof="error_code", + enum=gage_action_error.ActionErrorEnum.ActionError, + ) ad_group_criterion_customizer_error: ( gage_ad_group_criterion_customizer_error.AdGroupCriterionCustomizerErrorEnum.AdGroupCriterionCustomizerError ) = proto.Field( @@ -2601,6 +2631,22 @@ class ErrorCode(proto.Message): enum=gage_incentive_error.IncentiveErrorEnum.IncentiveError, ) ) + content_creator_insights_error: ( + gage_content_creator_insights_error.ContentCreatorInsightsErrorEnum.ContentCreatorInsightsError + ) = proto.Field( + proto.ENUM, + number=198, + oneof="error_code", + enum=gage_content_creator_insights_error.ContentCreatorInsightsErrorEnum.ContentCreatorInsightsError, + ) + video_reservation_error: ( + gage_video_reservation_error.VideoReservationErrorEnum.VideoReservationError + ) = proto.Field( + proto.ENUM, + number=199, + oneof="error_code", + enum=gage_video_reservation_error.VideoReservationErrorEnum.VideoReservationError, + ) class ErrorLocation(proto.Message): @@ -2670,6 +2716,8 @@ class ErrorDetails(proto.Message): budget_per_day_minimum_error_details (google.ads.googleads.v23.errors.types.BudgetPerDayMinimumErrorDetails): Details for a budget below per-day minimum error. + reservation_error_details (google.ads.googleads.v23.errors.types.ReservationErrorDetails): + Details for a reservation error. """ unpublished_error_code: str = proto.Field( @@ -2703,6 +2751,11 @@ class ErrorDetails(proto.Message): message="BudgetPerDayMinimumErrorDetails", ) ) + reservation_error_details: "ReservationErrorDetails" = proto.Field( + proto.MESSAGE, + number=7, + message="ReservationErrorDetails", + ) class PolicyViolationDetails(proto.Message): @@ -2921,4 +2974,41 @@ class BudgetPerDayMinimumErrorDetails(proto.Message): ) +class ReservationErrorDetails(proto.Message): + r"""Error details returned for BookCampaigns or QuoteCampaigns. + + Attributes: + campaign (str): + The resource name of the campaign affected by the error, as + it was specified in the request. It could contain a + temporary ID. Format: + customers/{customer_id}/campaigns/{campaign_id} + quotes (MutableSequence[google.ads.googleads.v23.common.types.CampaignReservationQuote]): + A list of proposed quotes for all the + campaigns in the request. For the failed + campaign, the given quote allows booking. + quote_signature (str): + A signature of the returned quote. The + signature covers the entire set of campaigns in + the request, and can be used in subsequent + requests for the same set of campaigns. + """ + + campaign: str = proto.Field( + proto.STRING, + number=1, + ) + quotes: MutableSequence[ + campaign_reservation_quote.CampaignReservationQuote + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=campaign_reservation_quote.CampaignReservationQuote, + ) + quote_signature: str = proto.Field( + proto.STRING, + number=3, + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/errors/types/request_error.py b/google/ads/googleads/v23/errors/types/request_error.py index 628895c3b..514743f89 100644 --- a/google/ads/googleads/v23/errors/types/request_error.py +++ b/google/ads/googleads/v23/errors/types/request_error.py @@ -74,6 +74,9 @@ class RequestError(proto.Enum): 'update'. TOO_MANY_MUTATE_OPERATIONS (13): Received too many entries in request. + TOO_MANY_ACTION_OPERATIONS (41): + Received too many action operations in + request. CANNOT_BE_EXECUTED_BY_MANAGER_ACCOUNT (14): Request cannot be executed by a manager account. @@ -131,6 +134,7 @@ class RequestError(proto.Enum): REQUIRED_FIELD_MISSING = 9 IMMUTABLE_FIELD = 11 TOO_MANY_MUTATE_OPERATIONS = 13 + TOO_MANY_ACTION_OPERATIONS = 41 CANNOT_BE_EXECUTED_BY_MANAGER_ACCOUNT = 14 CANNOT_MODIFY_FOREIGN_FIELD = 15 INVALID_ENUM_VALUE = 18 diff --git a/google/ads/googleads/v23/errors/types/shareable_preview_error.py b/google/ads/googleads/v23/errors/types/shareable_preview_error.py index 4825e6b62..477a0483a 100644 --- a/google/ads/googleads/v23/errors/types/shareable_preview_error.py +++ b/google/ads/googleads/v23/errors/types/shareable_preview_error.py @@ -48,12 +48,20 @@ class ShareablePreviewError(proto.Enum): ASSET_GROUP_DOES_NOT_EXIST_UNDER_THIS_CUSTOMER (3): asset group does not exist under this customer. + UNSUPPORTED_AD_TYPE (4): + Unsupported ad type for the given preview + type. + TOO_MANY_RESOURCES_IN_REQUEST (6): + The combined number of asset groups and ad + group ads exceeds the maximum of 10. """ UNSPECIFIED = 0 UNKNOWN = 1 TOO_MANY_ASSET_GROUPS_IN_REQUEST = 2 ASSET_GROUP_DOES_NOT_EXIST_UNDER_THIS_CUSTOMER = 3 + UNSUPPORTED_AD_TYPE = 4 + TOO_MANY_RESOURCES_IN_REQUEST = 6 __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/errors/types/user_list_customer_type_error.py b/google/ads/googleads/v23/errors/types/user_list_customer_type_error.py index 9057149cb..71068b379 100644 --- a/google/ads/googleads/v23/errors/types/user_list_customer_type_error.py +++ b/google/ads/googleads/v23/errors/types/user_list_customer_type_error.py @@ -53,7 +53,13 @@ class UserListCustomerTypeError(proto.Enum): 4. Qualified Leads - Converted Leads 5. Disengaged customers - Converted Leads 6. Disengaged customers - Qualified Leads - 7. Disengaged customers- Cart Abandoners + 7. Disengaged customers - Cart Abandoners + 8. Converted Leads - Loyalty Tier X Members (X = + 1..7) + 9. Qualified Leads - Loyalty Tier X Members (X = + 1..7) + 10. Loyalty Tier X Members - Loyalty Tier Y + Members (X != Y) NO_ACCESS_TO_USER_LIST (3): The account does not have access to the user list. diff --git a/google/ads/googleads/v23/errors/types/video_reservation_error.py b/google/ads/googleads/v23/errors/types/video_reservation_error.py new file mode 100644 index 000000000..bda1ddb6c --- /dev/null +++ b/google/ads/googleads/v23/errors/types/video_reservation_error.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.ads.googleads.v23.errors", + marshal="google.ads.googleads.v23", + manifest={ + "VideoReservationErrorEnum", + }, +) + + +class VideoReservationErrorEnum(proto.Message): + r"""Container for enum describing possible video reservation + errors. + + """ + + class VideoReservationError(proto.Enum): + r"""Enum describing possible video reservation errors. + + Values: + UNSPECIFIED (0): + Enum unspecified. + UNKNOWN (1): + The received error code is not known in this + version. + NEW_QUOTE_REQUIRED (2): + The quote has expired. + CAMPAIGN_END_TIME_TOO_DISTANT (3): + The campaign's end date has to be less than + 120 days from now. + BUDGET_TOO_SMALL (4): + The campaign budget is too small. To get a + quote, increase the budget. + CAMPAIGN_DURATION_TOO_SHORT (5): + The campaign must run for more than 24 hours. + CAMPAIGN_NOT_ENABLED (6): + The campaign must be enabled before booking. + NOT_ENOUGH_AVAILABLE_INVENTORY (7): + There aren't enough impressions available for + the campaigns settings and targeting. Broaden + the targeting or lower the budget of the + campaign to get a quote. + TARGETING_TOO_NARROW (8): + There aren't enough impressions available for + the campaign settings and targeting. + UNSUPPORTED_AD_GROUP_TYPE (9): + The type of the enabled ad group of this + campaign isn't supported. + UNSUPPORTED_BID_MODIFIER (10): + Bid modifiers other than 0% or -100% aren't + supported. + CANNOT_CHANGE_PRICING_MODEL (11): + The type of placement was changed. YouTube + Select lineups can only be paired with other + YouTube Select lineups. + INCOMPATIBLE_TARGETING (12): + More than one lineup was selected. Only one + lineup per campaign can be targeted. + UNSUPPORTED_FEATURE (13): + Some options in this campaign aren't + supported. + MISSING_ELECTION_CERTIFICATE (14): + The customer must be verified by Google to + run election ads in the targeted country. + CAMPAIGN_ENDED (15): + This campaign has ended. Select a campaign + that hasn't reached its end date. + UNSUPPORTED_BUDGET_PERIOD (16): + Daily budget isn't available for fixed CPM + campaigns. To use fixed CPM, enter a campaign + total budget. + EXACTLY_ONE_ENABLED_ADGROUP_REQUIRED (17): + The campaign must have exactly one enabled ad + group for reservation. + FREQUENCY_CAP_TOO_NARROW (18): + The frequency cap is lower than the minimum + allowed for an enabled campaign. Update the + frequency cap to either a daily cap or a weekly + cap with at least 3 impressions per week. + TARGETED_PACK_NEEDS_DEAL (19): + The targeted country requires either a deal + or a market rate. + DEAL_CURRENCY_MISMATCH (20): + The account is set to a currency that doesn't + match the currency of the rate card for the + targeted video lineups. + CANNOT_HOLD_CONTRACT (21): + Quote holds are unavailable for this campaign + configuration. + CUSTOMER_NOT_ENABLED (22): + The account is suspended. Contact support for + more info. + CUSTOMER_NOT_ALLOWED (23): + The customer doesn't have permission to + request a quote. Contact the account owner for + more info. + INVALID_ACCOUNT_TYPE (24): + This account type can't request quotes. Use a + different account or contact support for more + info. + ACCOUNT_IS_MANAGER (25): + Google Account Managers can't request quotes + for reservation campaigns. + SEASONAL_LINEUP_BOOKING_WINDOW_NOT_OPEN (26): + The booking window for this lineup is not + open yet. + SEASONAL_LINEUP_END_DATE_OFF_SEASON (27): + The campaign end date is later than the + allowable end date for this lineup. To continue + booking, choose an earlier end date. + SEASONAL_LINEUP_GEO_TARGETING_TOO_NARROW (28): + There aren't enough impressions available for + the campaign settings and targeting. Broaden the + location targeting to get a quote. + NO_MARKET_RATE_CARD_OR_BASE_RATE (29): + The market rate for the targeted product + isn't available. + STALE_QUOTE (30): + The quote is stale, get a new quote and try + again. + LINEUP_NOT_ALLOWED (31): + Some of the targeted video lineups aren't + available for reservation campaigns. + UNSUPPORTED_BIDDING_STRATEGY (32): + This bidding strategy is not supported for + reservation. + UNSUPPORTED_POSITIVE_GEO_TARGET_TYPE (33): + The campaign settings contain a positive geo + target type which is not allowed, for example + Audio ads support PRESENCE only. + VALIDATE_ONLY_REQUIRED (34): + Only validate_only requests are supported. + TOO_MANY_CAMPAIGNS (35): + Too many campaigns in request. + """ + + UNSPECIFIED = 0 + UNKNOWN = 1 + NEW_QUOTE_REQUIRED = 2 + CAMPAIGN_END_TIME_TOO_DISTANT = 3 + BUDGET_TOO_SMALL = 4 + CAMPAIGN_DURATION_TOO_SHORT = 5 + CAMPAIGN_NOT_ENABLED = 6 + NOT_ENOUGH_AVAILABLE_INVENTORY = 7 + TARGETING_TOO_NARROW = 8 + UNSUPPORTED_AD_GROUP_TYPE = 9 + UNSUPPORTED_BID_MODIFIER = 10 + CANNOT_CHANGE_PRICING_MODEL = 11 + INCOMPATIBLE_TARGETING = 12 + UNSUPPORTED_FEATURE = 13 + MISSING_ELECTION_CERTIFICATE = 14 + CAMPAIGN_ENDED = 15 + UNSUPPORTED_BUDGET_PERIOD = 16 + EXACTLY_ONE_ENABLED_ADGROUP_REQUIRED = 17 + FREQUENCY_CAP_TOO_NARROW = 18 + TARGETED_PACK_NEEDS_DEAL = 19 + DEAL_CURRENCY_MISMATCH = 20 + CANNOT_HOLD_CONTRACT = 21 + CUSTOMER_NOT_ENABLED = 22 + CUSTOMER_NOT_ALLOWED = 23 + INVALID_ACCOUNT_TYPE = 24 + ACCOUNT_IS_MANAGER = 25 + SEASONAL_LINEUP_BOOKING_WINDOW_NOT_OPEN = 26 + SEASONAL_LINEUP_END_DATE_OFF_SEASON = 27 + SEASONAL_LINEUP_GEO_TARGETING_TOO_NARROW = 28 + NO_MARKET_RATE_CARD_OR_BASE_RATE = 29 + STALE_QUOTE = 30 + LINEUP_NOT_ALLOWED = 31 + UNSUPPORTED_BIDDING_STRATEGY = 32 + UNSUPPORTED_POSITIVE_GEO_TARGET_TYPE = 33 + VALIDATE_ONLY_REQUIRED = 34 + TOO_MANY_CAMPAIGNS = 35 + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/gapic_metadata.json b/google/ads/googleads/v23/gapic_metadata.json index 775f7ac9b..1b92beaef 100644 --- a/google/ads/googleads/v23/gapic_metadata.json +++ b/google/ads/googleads/v23/gapic_metadata.json @@ -2911,6 +2911,40 @@ } } }, + "ReservationService": { + "clients": { + "grpc": { + "libraryClient": "ReservationServiceClient", + "rpcs": { + "BookCampaigns": { + "methods": [ + "book_campaigns" + ] + }, + "QuoteCampaigns": { + "methods": [ + "quote_campaigns" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ReservationServiceAsyncClient", + "rpcs": { + "BookCampaigns": { + "methods": [ + "book_campaigns" + ] + }, + "QuoteCampaigns": { + "methods": [ + "quote_campaigns" + ] + } + } + } + } + }, "ShareablePreviewService": { "clients": { "grpc": { diff --git a/google/ads/googleads/v23/resources/__init__.py b/google/ads/googleads/v23/resources/__init__.py index 53388e29b..c46158378 100644 --- a/google/ads/googleads/v23/resources/__init__.py +++ b/google/ads/googleads/v23/resources/__init__.py @@ -70,6 +70,8 @@ from .types.android_privacy_shared_key_google_network_type import ( AndroidPrivacySharedKeyGoogleNetworkType, ) +from .types.app_top_combination_view import AdGroupCreativeAssetCombinationData +from .types.app_top_combination_view import AppTopCombinationView from .types.applied_incentive import AppliedIncentive from .types.asset import Asset from .types.asset import AssetFieldTypePolicySummary @@ -325,6 +327,7 @@ from .types.user_list_customer_type import UserListCustomerType from .types.user_location_view import UserLocationView from .types.video import Video +from .types.video_enhancement import VideoEnhancement from .types.webpage_view import WebpageView from .types.youtube_video_upload import YouTubeVideoUpload @@ -442,6 +445,7 @@ def _get_version(dependency_name): "AdGroupAssetSet", "AdGroupAudienceView", "AdGroupBidModifier", + "AdGroupCreativeAssetCombinationData", "AdGroupCriterion", "AdGroupCriterionCustomizer", "AdGroupCriterionLabel", @@ -461,6 +465,7 @@ def _get_version(dependency_name): "AndroidPrivacySharedKeyGoogleAdGroup", "AndroidPrivacySharedKeyGoogleCampaign", "AndroidPrivacySharedKeyGoogleNetworkType", + "AppTopCombinationView", "AppliedIncentive", "Asset", "AssetCoverage", @@ -663,6 +668,7 @@ def _get_version(dependency_name): "UserLocationView", "Video", "VideoCustomer", + "VideoEnhancement", "WebpageView", "YouTubeVideoUpload", "YoutubeVideoIdentifier", diff --git a/google/ads/googleads/v23/resources/types/__init__.py b/google/ads/googleads/v23/resources/types/__init__.py index b9f3919dc..c86e18c89 100644 --- a/google/ads/googleads/v23/resources/types/__init__.py +++ b/google/ads/googleads/v23/resources/types/__init__.py @@ -101,6 +101,10 @@ from .android_privacy_shared_key_google_network_type import ( AndroidPrivacySharedKeyGoogleNetworkType, ) +from .app_top_combination_view import ( + AdGroupCreativeAssetCombinationData, + AppTopCombinationView, +) from .applied_incentive import ( AppliedIncentive, ) @@ -614,6 +618,9 @@ from .video import ( Video, ) +from .video_enhancement import ( + VideoEnhancement, +) from .webpage_view import ( WebpageView, ) @@ -654,6 +661,8 @@ "AndroidPrivacySharedKeyGoogleAdGroup", "AndroidPrivacySharedKeyGoogleCampaign", "AndroidPrivacySharedKeyGoogleNetworkType", + "AdGroupCreativeAssetCombinationData", + "AppTopCombinationView", "AppliedIncentive", "Asset", "AssetFieldTypePolicySummary", @@ -861,6 +870,7 @@ "UserListCustomerType", "UserLocationView", "Video", + "VideoEnhancement", "WebpageView", "YouTubeVideoUpload", ) diff --git a/google/ads/googleads/v23/resources/types/ad_group_ad.py b/google/ads/googleads/v23/resources/types/ad_group_ad.py index 518901de9..9599159b3 100644 --- a/google/ads/googleads/v23/resources/types/ad_group_ad.py +++ b/google/ads/googleads/v23/resources/types/ad_group_ad.py @@ -68,6 +68,22 @@ class AdGroupAd(proto.Message): This field is a member of `oneof`_ ``_ad_group``. ad (google.ads.googleads.v23.resources.types.Ad): Immutable. The ad. + start_date_time (str): + The date and time when ad group ad starts + serving. This is added on top of the campaign's + start date and time, if present, to further + restrict the duration of an ad group ad. The + timestamp is in the customer's time zone and in + "yyyy-MM-dd HH:mm:ss" format. Only supported for + some ad types. + end_date_time (str): + The last day and time when ad group ad + serves. This is added on top of the campaign's + end date and time, if present, to further + restrict the duration of an ad group ad. The + timestamp is in the customer's time zone and in + "yyyy-MM-dd HH:mm:ss" format. Only supported for + some ad types. policy_summary (google.ads.googleads.v23.resources.types.AdGroupAdPolicySummary): Output only. Policy information for the ad. ad_strength (google.ads.googleads.v23.enums.types.AdStrengthEnum.AdStrength): @@ -117,6 +133,14 @@ class AdGroupAd(proto.Message): number=5, message=gagr_ad.Ad, ) + start_date_time: str = proto.Field( + proto.STRING, + number=20, + ) + end_date_time: str = proto.Field( + proto.STRING, + number=21, + ) policy_summary: "AdGroupAdPolicySummary" = proto.Field( proto.MESSAGE, number=6, diff --git a/google/ads/googleads/v23/resources/types/app_top_combination_view.py b/google/ads/googleads/v23/resources/types/app_top_combination_view.py new file mode 100644 index 000000000..45fcb18e3 --- /dev/null +++ b/google/ads/googleads/v23/resources/types/app_top_combination_view.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableSequence + +import proto # type: ignore + +from google.ads.googleads.v23.common.types import asset_usage + + +__protobuf__ = proto.module( + package="google.ads.googleads.v23.resources", + marshal="google.ads.googleads.v23", + manifest={ + "AppTopCombinationView", + "AdGroupCreativeAssetCombinationData", + }, +) + + +class AppTopCombinationView(proto.Message): + r"""A view resource in the App Top Combination Report. + + Attributes: + resource_name (str): + Output only. The resource name of the app top combination + view. App Top Combination view resource names have the form: + ``customers/{customer_id}/appTopCombinationViews/{ad_group_id}~{ad_id}~{asset_combination_category}`` + ad_group_top_combinations (MutableSequence[google.ads.googleads.v23.resources.types.AdGroupCreativeAssetCombinationData]): + Output only. The top combinations of assets + that served together. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + ad_group_top_combinations: MutableSequence[ + "AdGroupCreativeAssetCombinationData" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="AdGroupCreativeAssetCombinationData", + ) + + +class AdGroupCreativeAssetCombinationData(proto.Message): + r"""Ad group asset combination data + + Attributes: + asset_combination_served_assets (MutableSequence[google.ads.googleads.v23.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/v23/resources/types/campaign.py b/google/ads/googleads/v23/resources/types/campaign.py index e0154de58..36473ec83 100644 --- a/google/ads/googleads/v23/resources/types/campaign.py +++ b/google/ads/googleads/v23/resources/types/campaign.py @@ -216,8 +216,7 @@ class Campaign(proto.Message): network_settings (google.ads.googleads.v23.resources.types.Campaign.NetworkSettings): The network settings for the campaign. hotel_setting (google.ads.googleads.v23.resources.types.Campaign.HotelSettingInfo): - Immutable. The hotel setting for the - campaign. + The hotel setting for the campaign. dynamic_search_ads_setting (google.ads.googleads.v23.resources.types.Campaign.DynamicSearchAdsSetting): The setting for controlling Dynamic Search Ads (DSA). @@ -598,9 +597,9 @@ class NetworkSettings(proto.Message): 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``). + Whether ads will be served on sites in the Google Search + Partners Network (requires ``target_google_search`` to also + be ``true``). This field is a member of `oneof`_ ``_target_search_network``. target_content_network (bool): @@ -611,9 +610,12 @@ class NetworkSettings(proto.Message): 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. + Whether ads will be served on the partner network. This is + available only to some select partner accounts. Unless you + have been instructed to use this field, it likely does not + apply to your account. This does not control whether ads + will be served on Google Search Partners Network; use + ``target_search_network`` for that instead. This field is a member of `oneof`_ ``_target_partner_search_network``. target_youtube (bool): @@ -665,9 +667,15 @@ class HotelSettingInfo(proto.Message): Attributes: hotel_center_id (int): - Immutable. The linked Hotel Center account. + The linked Hotel Center account. This field is a member of `oneof`_ ``_hotel_center_id``. + disable_hotel_setting (bool): + Disable the optional hotel setting. This + field is currently supported only for Demand Gen + campaigns. + + This field is a member of `oneof`_ ``_disable_hotel_setting``. """ hotel_center_id: int = proto.Field( @@ -675,6 +683,11 @@ class HotelSettingInfo(proto.Message): number=2, optional=True, ) + disable_hotel_setting: bool = proto.Field( + proto.BOOL, + number=3, + optional=True, + ) class DynamicSearchAdsSetting(proto.Message): r"""The setting for controlling Dynamic Search Ads (DSA). diff --git a/google/ads/googleads/v23/resources/types/video.py b/google/ads/googleads/v23/resources/types/video.py index e9be16bcc..2931c9850 100644 --- a/google/ads/googleads/v23/resources/types/video.py +++ b/google/ads/googleads/v23/resources/types/video.py @@ -31,6 +31,12 @@ class Video(proto.Message): r"""A video. + If the video has any enhancements, the stats on all of them will + be aggregated and displayed on this video resource. To get stats + for a specific enhancement, use the VideoEnhancement resource + instead. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields Attributes: diff --git a/google/ads/googleads/v23/resources/types/video_enhancement.py b/google/ads/googleads/v23/resources/types/video_enhancement.py new file mode 100644 index 000000000..419544f32 --- /dev/null +++ b/google/ads/googleads/v23/resources/types/video_enhancement.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + +from google.ads.googleads.v23.enums.types import video_enhancement_source + + +__protobuf__ = proto.module( + package="google.ads.googleads.v23.resources", + marshal="google.ads.googleads.v23", + manifest={ + "VideoEnhancement", + }, +) + + +class VideoEnhancement(proto.Message): + r"""Represents a video that can include both advertiser uploaded videos + or enhancements generated from the advertiser uploaded videos. Only + publicly available videos are returned. + + Each row in this resource represents either the video uploaded by + the advertiser or each specific variation of it. In contrast, the + ``Video`` resource represents only the advertiser-provided video and + would aggregate metrics across all its variations (including + enhancements). {-- next tag to use: 5 --} + + Attributes: + resource_name (str): + Output only. The resource name of the video enhancement. + Video enhancement resource names have the form: + + ``customers/{customer_id}/videoEnhancements/{video_id}`` + duration_millis (int): + Output only. Duration of this video, in + milliseconds. + source (google.ads.googleads.v23.enums.types.VideoEnhancementSourceEnum.VideoEnhancementSource): + Output only. The source of the video (e.g. + advertiser or enhanced by Google Ads). + title (str): + Output only. Title of this video. + """ + + resource_name: str = proto.Field( + proto.STRING, + number=1, + ) + duration_millis: int = proto.Field( + proto.INT64, + number=2, + ) + source: ( + video_enhancement_source.VideoEnhancementSourceEnum.VideoEnhancementSource + ) = proto.Field( + proto.ENUM, + number=3, + enum=video_enhancement_source.VideoEnhancementSourceEnum.VideoEnhancementSource, + ) + title: str = proto.Field( + proto.STRING, + number=4, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/services/__init__.py b/google/ads/googleads/v23/services/__init__.py index fb3f814f9..f403580dd 100644 --- a/google/ads/googleads/v23/services/__init__.py +++ b/google/ads/googleads/v23/services/__init__.py @@ -755,6 +755,7 @@ TargetFrequencySettings, Targeting, YouTubeSelectLineUp, + YouTubeSelectLineUpTargeting, YouTubeSelectSettings, ) from .types.recommendation_service import ( @@ -779,6 +780,12 @@ MutateRemarketingActionsResponse, RemarketingActionOperation, ) +from .types.reservation_service import ( + BookCampaignsRequest, + BookCampaignsResponse, + QuoteCampaignsRequest, + QuoteCampaignsResponse, +) from .types.shareable_preview_service import ( AssetGroupIdentifier, GenerateShareablePreviewsRequest, @@ -786,6 +793,7 @@ ShareablePreview, ShareablePreviewOrError, ShareablePreviewResult, + YouTubeLivePreviewResult, ) from .types.shared_criterion_service import ( MutateSharedCriteriaRequest, @@ -1410,6 +1418,7 @@ "TargetFrequencySettings", "Targeting", "YouTubeSelectLineUp", + "YouTubeSelectLineUpTargeting", "YouTubeSelectSettings", "ApplyRecommendationOperation", "ApplyRecommendationRequest", @@ -1427,12 +1436,17 @@ "MutateRemarketingActionsRequest", "MutateRemarketingActionsResponse", "RemarketingActionOperation", + "BookCampaignsRequest", + "BookCampaignsResponse", + "QuoteCampaignsRequest", + "QuoteCampaignsResponse", "AssetGroupIdentifier", "GenerateShareablePreviewsRequest", "GenerateShareablePreviewsResponse", "ShareablePreview", "ShareablePreviewOrError", "ShareablePreviewResult", + "YouTubeLivePreviewResult", "MutateSharedCriteriaRequest", "MutateSharedCriteriaResponse", "MutateSharedCriterionResult", diff --git a/google/ads/googleads/v23/services/services/google_ads_service/async_client.py b/google/ads/googleads/v23/services/services/google_ads_service/async_client.py index 9f47d0d57..549704ae8 100644 --- a/google/ads/googleads/v23/services/services/google_ads_service/async_client.py +++ b/google/ads/googleads/v23/services/services/google_ads_service/async_client.py @@ -235,6 +235,12 @@ class GoogleAdsServiceAsyncClient: parse_applied_incentive_path = staticmethod( GoogleAdsServiceClient.parse_applied_incentive_path ) + app_top_combination_view_path = staticmethod( + GoogleAdsServiceClient.app_top_combination_view_path + ) + parse_app_top_combination_view_path = staticmethod( + GoogleAdsServiceClient.parse_app_top_combination_view_path + ) asset_path = staticmethod(GoogleAdsServiceClient.asset_path) parse_asset_path = staticmethod(GoogleAdsServiceClient.parse_asset_path) asset_field_type_view_path = staticmethod( @@ -1063,6 +1069,12 @@ class GoogleAdsServiceAsyncClient: ) video_path = staticmethod(GoogleAdsServiceClient.video_path) parse_video_path = staticmethod(GoogleAdsServiceClient.parse_video_path) + video_enhancement_path = staticmethod( + GoogleAdsServiceClient.video_enhancement_path + ) + parse_video_enhancement_path = staticmethod( + GoogleAdsServiceClient.parse_video_enhancement_path + ) webpage_view_path = staticmethod(GoogleAdsServiceClient.webpage_view_path) parse_webpage_view_path = staticmethod( GoogleAdsServiceClient.parse_webpage_view_path @@ -1537,10 +1549,12 @@ async def mutate( timeout: Union[float, object] = gapic_v1.method.DEFAULT, metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), ) -> 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. + r"""Executes mutate and actions operations. Mutate operations + create, update, or remove resources. Actions perform custom + operations. This method supports atomic transactions with + multiple types of resources and actions. For example, you can + atomically create a campaign and a campaign budget, or perform + up to thousands of mutates atomically. This method is essentially a wrapper around a series of mutate methods. The only features it offers over calling those methods diff --git a/google/ads/googleads/v23/services/services/google_ads_service/client.py b/google/ads/googleads/v23/services/services/google_ads_service/client.py index 284a36b89..192943e4f 100644 --- a/google/ads/googleads/v23/services/services/google_ads_service/client.py +++ b/google/ads/googleads/v23/services/services/google_ads_service/client.py @@ -911,6 +911,30 @@ def parse_applied_incentive_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def app_top_combination_view_path( + customer_id: str, + ad_group_id: str, + ad_id: str, + asset_combination_category: str, + ) -> str: + """Returns a fully-qualified app_top_combination_view string.""" + return "customers/{customer_id}/appTopCombinationViews/{ad_group_id}~{ad_id}~{asset_combination_category}".format( + customer_id=customer_id, + ad_group_id=ad_group_id, + ad_id=ad_id, + asset_combination_category=asset_combination_category, + ) + + @staticmethod + def parse_app_top_combination_view_path(path: str) -> Dict[str, str]: + """Parses a app_top_combination_view path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/appTopCombinationViews/(?P.+?)~(?P.+?)~(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def asset_path( customer_id: str, @@ -4040,6 +4064,26 @@ def parse_video_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def video_enhancement_path( + customer_id: str, + video_enhancement: str, + ) -> str: + """Returns a fully-qualified video_enhancement string.""" + return "customers/{customer_id}/videoEnhancements/{video_enhancement}".format( + customer_id=customer_id, + video_enhancement=video_enhancement, + ) + + @staticmethod + def parse_video_enhancement_path(path: str) -> Dict[str, str]: + """Parses a video_enhancement path into its component segments.""" + m = re.match( + r"^customers/(?P.+?)/videoEnhancements/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def webpage_view_path( customer_id: str, @@ -4824,10 +4868,12 @@ def mutate( timeout: Union[float, object] = gapic_v1.method.DEFAULT, metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), ) -> 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. + r"""Executes mutate and actions operations. Mutate operations + create, update, or remove resources. Actions perform custom + operations. This method supports atomic transactions with + multiple types of resources and actions. For example, you can + atomically create a campaign and a campaign budget, or perform + up to thousands of mutates atomically. This method is essentially a wrapper around a series of mutate methods. The only features it offers over calling those methods diff --git a/google/ads/googleads/v23/services/services/google_ads_service/transports/grpc.py b/google/ads/googleads/v23/services/services/google_ads_service/transports/grpc.py index 4ca2449f1..4024fedbc 100644 --- a/google/ads/googleads/v23/services/services/google_ads_service/transports/grpc.py +++ b/google/ads/googleads/v23/services/services/google_ads_service/transports/grpc.py @@ -420,10 +420,12 @@ def mutate( ]: 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. + Executes mutate and actions operations. Mutate operations + create, update, or remove resources. Actions perform custom + operations. This method supports atomic transactions with + multiple types of resources and actions. For example, you can + atomically create a campaign and a campaign budget, or perform + up to thousands of mutates atomically. This method is essentially a wrapper around a series of mutate methods. The only features it offers over calling those methods diff --git a/google/ads/googleads/v23/services/services/google_ads_service/transports/grpc_asyncio.py b/google/ads/googleads/v23/services/services/google_ads_service/transports/grpc_asyncio.py index 4e44ef62d..d892678f0 100644 --- a/google/ads/googleads/v23/services/services/google_ads_service/transports/grpc_asyncio.py +++ b/google/ads/googleads/v23/services/services/google_ads_service/transports/grpc_asyncio.py @@ -426,10 +426,12 @@ def mutate( ]: 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. + Executes mutate and actions operations. Mutate operations + create, update, or remove resources. Actions perform custom + operations. This method supports atomic transactions with + multiple types of resources and actions. For example, you can + atomically create a campaign and a campaign budget, or perform + up to thousands of mutates atomically. This method is essentially a wrapper around a series of mutate methods. The only features it offers over calling those methods diff --git a/google/ads/googleads/v23/services/services/reservation_service/__init__.py b/google/ads/googleads/v23/services/services/reservation_service/__init__.py new file mode 100644 index 000000000..08b898ebb --- /dev/null +++ b/google/ads/googleads/v23/services/services/reservation_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from .client import ReservationServiceClient +from .async_client import ReservationServiceAsyncClient + +__all__ = ( + "ReservationServiceClient", + "ReservationServiceAsyncClient", +) diff --git a/google/ads/googleads/v23/services/services/reservation_service/async_client.py b/google/ads/googleads/v23/services/services/reservation_service/async_client.py new file mode 100644 index 000000000..4c3526ac4 --- /dev/null +++ b/google/ads/googleads/v23/services/services/reservation_service/async_client.py @@ -0,0 +1,489 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import logging as std_logging +from typing import Callable, Optional, Sequence, Tuple, Union + +from google.ads.googleads.v23 import gapic_version as package_version + +from google.api_core.client_options import ClientOptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + + +try: + OptionalRetry = Union[ + retries.AsyncRetry, gapic_v1.method._MethodDefault, None + ] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.AsyncRetry, object, None] # type: ignore + +from google.ads.googleads.v23.services.types import reservation_service +from .transports.base import ReservationServiceTransport, DEFAULT_CLIENT_INFO +from .client import ReservationServiceClient + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + + +class ReservationServiceAsyncClient: + """Service for reservation related operations. + This service is not publicly available. + """ + + _client: ReservationServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ReservationServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ReservationServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + ReservationServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = ReservationServiceClient._DEFAULT_UNIVERSE + + common_billing_account_path = staticmethod( + ReservationServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ReservationServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + ReservationServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + ReservationServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ReservationServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ReservationServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + ReservationServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + ReservationServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + ReservationServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + ReservationServiceClient.parse_common_location_path + ) + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ReservationServiceAsyncClient: The constructed client. + """ + return ReservationServiceClient.from_service_account_info.__func__(ReservationServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ReservationServiceAsyncClient: The constructed client. + """ + return ReservationServiceClient.from_service_account_file.__func__(ReservationServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ReservationServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ReservationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ReservationServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ReservationServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ReservationServiceTransport, + Callable[..., ReservationServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the reservation service async client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,ReservationServiceTransport,Callable[..., ReservationServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport to use. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the ReservationServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client = ReservationServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ): # pragma: NO COVER + _LOGGER.debug( + "Created client `google.ads.googleads.v23.services.ReservationServiceAsyncClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v23.services.ReservationService", + "universeDomain": getattr( + self._client._transport._credentials, + "universe_domain", + "", + ), + "credentialsType": f"{type(self._client._transport._credentials).__module__}.{type(self._client._transport._credentials).__qualname__}", + "credentialsInfo": getattr( + self.transport._credentials, + "get_cred_info", + lambda: None, + )(), + } + if hasattr(self._client._transport, "_credentials") + else { + "serviceName": "google.ads.googleads.v23.services.ReservationService", + "credentialsType": None, + } + ), + ) + + async def quote_campaigns( + self, + request: Optional[ + Union[reservation_service.QuoteCampaignsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reservation_service.QuoteCampaignsResponse: + r"""Proposes quotes for booking campaigns. + This request can have a latency of 30 seconds. + + Args: + request (Optional[Union[google.ads.googleads.v23.services.types.QuoteCampaignsRequest, dict]]): + The request object. Request message for + [ReservationService.QuoteCampaigns][google.ads.googleads.v23.services.ReservationService.QuoteCampaigns]. + customer_id (:class:`str`): + Required. The ID of the customer + making the request. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.ads.googleads.v23.services.types.QuoteCampaignsResponse: + Response message for + [ReservationService.QuoteCampaigns][google.ads.googleads.v23.services.ReservationService.QuoteCampaigns]. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [customer_id] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, reservation_service.QuoteCampaignsRequest): + request = reservation_service.QuoteCampaignsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.quote_campaigns + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def book_campaigns( + self, + request: Optional[ + Union[reservation_service.BookCampaignsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reservation_service.BookCampaignsResponse: + r"""Books the requested campaigns. + This request can have a latency of 30 seconds. + + Args: + request (Optional[Union[google.ads.googleads.v23.services.types.BookCampaignsRequest, dict]]): + The request object. Request message for + [ReservationService.BookCampaigns][google.ads.googleads.v23.services.ReservationService.BookCampaigns]. + customer_id (:class:`str`): + Required. The ID of the customer + making the request. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.ads.googleads.v23.services.types.BookCampaignsResponse: + Response message for + [ReservationService.BookCampaigns][google.ads.googleads.v23.services.ReservationService.BookCampaigns]. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [customer_id] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, reservation_service.BookCampaignsRequest): + request = reservation_service.BookCampaignsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.book_campaigns + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ReservationServiceAsyncClient": + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + + +__all__ = ("ReservationServiceAsyncClient",) diff --git a/google/ads/googleads/v23/services/services/reservation_service/client.py b/google/ads/googleads/v23/services/services/reservation_service/client.py new file mode 100644 index 000000000..8cb4de0f7 --- /dev/null +++ b/google/ads/googleads/v23/services/services/reservation_service/client.py @@ -0,0 +1,924 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +from http import HTTPStatus +import json +import logging as std_logging +import os +import re +from typing import Dict, Callable, Optional, Sequence, Tuple, Type, Union, cast +import warnings + +from google.ads.googleads.v23 import gapic_version as package_version + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + +from google.ads.googleads.v23.services.types import reservation_service +from .transports.base import ReservationServiceTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import ReservationServiceGrpcTransport +from .transports.grpc_asyncio import ReservationServiceGrpcAsyncIOTransport + + +class ReservationServiceClientMeta(type): + """Metaclass for the ReservationService client. + + This provides class-level methods for building and retrieving + support objects (e.g. transport) without polluting the client instance + objects. + """ + + _transport_registry = ( + OrderedDict() + ) # type: Dict[str, Type[ReservationServiceTransport]] + _transport_registry["grpc"] = ReservationServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ReservationServiceGrpcAsyncIOTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ReservationServiceTransport]: + """Returns an appropriate transport class. + + Args: + label: The name of the desired transport. If none is + provided, then the first transport in the registry is used. + + Returns: + The transport class to use. + """ + # If a specific transport is requested, return that one. + if label: + return cls._transport_registry[label] + + # No transport is requested; return the default (that is, the first one + # in the dictionary). + return next(iter(cls._transport_registry.values())) + + +class ReservationServiceClient(metaclass=ReservationServiceClientMeta): + """Service for reservation related operations. + This service is not publicly available. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "googleads.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "googleads.{UNIVERSE_DOMAIN}" + _DEFAULT_UNIVERSE = "googleapis.com" + + @staticmethod + def _use_client_cert_effective(): + """Returns whether client certificate should be used for mTLS if the + google-auth version supports should_use_client_cert automatic mTLS enablement. + + Alternatively, read from the GOOGLE_API_USE_CLIENT_CERTIFICATE env var. + + Returns: + bool: whether client certificate should be used for mTLS + Raises: + ValueError: (If using a version of google-auth without should_use_client_cert and + GOOGLE_API_USE_CLIENT_CERTIFICATE is set to an unexpected value.) + """ + # check if google-auth version supports should_use_client_cert for automatic mTLS enablement + if hasattr(mtls, "should_use_client_cert"): # pragma: NO COVER + return mtls.should_use_client_cert() + else: # pragma: NO COVER + # if unsupported, fallback to reading from env var + use_client_cert_str = os.getenv( + "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" + ).lower() + if use_client_cert_str not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be" + " either `true` or `false`" + ) + return use_client_cert_str == "true" + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ReservationServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info( + info + ) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ReservationServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file( + filename + ) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + from_service_account_json = from_service_account_file + + @property + def transport(self) -> ReservationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ReservationServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def common_billing_account_path( + billing_account: str, + ) -> str: + """Returns a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path( + folder: str, + ) -> str: + """Returns a fully-qualified folder string.""" + return "folders/{folder}".format( + folder=folder, + ) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path( + organization: str, + ) -> str: + """Returns a fully-qualified organization string.""" + return "organizations/{organization}".format( + organization=organization, + ) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path( + project: str, + ) -> str: + """Returns a fully-qualified project string.""" + return "projects/{project}".format( + project=project, + ) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path( + project: str, + location: str, + ) -> str: + """Returns a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)$", path + ) + return m.groupdict() if m else {} + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[client_options_lib.ClientOptions] = None + ): + """Deprecated. Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + + warnings.warn( + "get_mtls_endpoint_and_cert_source is deprecated. Use the api_endpoint property instead.", + DeprecationWarning, + ) + if client_options is None: + client_options = client_options_lib.ClientOptions() + use_client_cert = ReservationServiceClient._use_client_cert_effective() + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Figure out the client cert source to use. + client_cert_source = None + if use_client_cert: + if client_options.client_cert_source: + client_cert_source = client_options.client_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + api_endpoint = cls.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = cls.DEFAULT_ENDPOINT + + return api_endpoint, client_cert_source + + @staticmethod + def _read_environment_variables(): + """Returns the environment variables used by the client. + + Returns: + Tuple[bool, str, str]: returns the GOOGLE_API_USE_CLIENT_CERTIFICATE, + GOOGLE_API_USE_MTLS_ENDPOINT, and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables. + + Raises: + ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not + any of ["true", "false"]. + google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT + is not any of ["auto", "never", "always"]. + """ + use_client_cert = ReservationServiceClient._use_client_cert_effective() + use_mtls_endpoint = os.getenv( + "GOOGLE_API_USE_MTLS_ENDPOINT", "auto" + ).lower() + universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN") + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + return use_client_cert, use_mtls_endpoint, universe_domain_env + + @staticmethod + def _get_client_cert_source(provided_cert_source, use_cert_flag): + """Return the client cert source to be used by the client. + + Args: + provided_cert_source (bytes): The client certificate source provided. + use_cert_flag (bool): A flag indicating whether to use the client certificate. + + Returns: + bytes or None: The client cert source to be used by the client. + """ + client_cert_source = None + if use_cert_flag: + if provided_cert_source: + client_cert_source = provided_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + return client_cert_source + + @staticmethod + def _get_api_endpoint( + api_override, client_cert_source, universe_domain, use_mtls_endpoint + ): + """Return the API endpoint used by the client. + + Args: + api_override (str): The API endpoint override. If specified, this is always + the return value of this function and the other arguments are not used. + client_cert_source (bytes): The client certificate source used by the client. + universe_domain (str): The universe domain used by the client. + use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters. + Possible values are "always", "auto", or "never". + + Returns: + str: The API endpoint to be used by the client. + """ + if api_override is not None: + api_endpoint = api_override + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + _default_universe = ReservationServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ReservationServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + ReservationServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=universe_domain + ) + ) + return api_endpoint + + @staticmethod + def _get_universe_domain( + client_universe_domain: Optional[str], + universe_domain_env: Optional[str], + ) -> str: + """Return the universe domain used by the client. + + Args: + client_universe_domain (Optional[str]): The universe domain configured via the client options. + universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable. + + Returns: + str: The universe domain to be used by the client. + + Raises: + ValueError: If the universe domain is an empty string. + """ + universe_domain = ReservationServiceClient._DEFAULT_UNIVERSE + if client_universe_domain is not None: + universe_domain = client_universe_domain + elif universe_domain_env is not None: + universe_domain = universe_domain_env + if len(universe_domain.strip()) == 0: + raise ValueError("Universe Domain cannot be an empty string.") + return universe_domain + + def _validate_universe_domain(self): + """Validates client's and credentials' universe domains are consistent. + + Returns: + bool: True iff the configured universe domain is valid. + + Raises: + ValueError: If the configured universe domain is not valid. + """ + + # NOTE (b/349488459): universe validation is disabled until further notice. + return True + + def _add_cred_info_for_auth_errors( + self, error: core_exceptions.GoogleAPICallError + ) -> None: + """Adds credential info string to error details for 401/403/404 errors. + + Args: + error (google.api_core.exceptions.GoogleAPICallError): The error to add the cred info. + """ + if error.code not in [ + HTTPStatus.UNAUTHORIZED, + HTTPStatus.FORBIDDEN, + HTTPStatus.NOT_FOUND, + ]: + return + + cred = self._transport._credentials + + # get_cred_info is only available in google-auth>=2.35.0 + if not hasattr(cred, "get_cred_info"): + return + + # ignore the type check since pypy test fails when get_cred_info + # is not available + cred_info = cred.get_cred_info() # type: ignore + if cred_info and hasattr(error._details, "append"): + error._details.append(json.dumps(cred_info)) + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used by the client instance. + """ + return self._universe_domain + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + ReservationServiceTransport, + Callable[..., ReservationServiceTransport], + ] + ] = None, + client_options: Optional[ + Union[client_options_lib.ClientOptions, dict] + ] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the reservation service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,ReservationServiceTransport,Callable[..., ReservationServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the ReservationServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that the ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client_options = client_options + if isinstance(self._client_options, dict): + self._client_options = client_options_lib.from_dict( + self._client_options + ) + if self._client_options is None: + self._client_options = client_options_lib.ClientOptions() + self._client_options = cast( + client_options_lib.ClientOptions, self._client_options + ) + + universe_domain_opt = getattr( + self._client_options, "universe_domain", None + ) + + ( + self._use_client_cert, + self._use_mtls_endpoint, + self._universe_domain_env, + ) = ReservationServiceClient._read_environment_variables() + self._client_cert_source = ( + ReservationServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = ReservationServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + if CLIENT_LOGGING_SUPPORTED: # pragma: NO COVER + # Setup logging. + client_logging.initialize_logging() + + api_key_value = getattr(self._client_options, "api_key", None) + if api_key_value and credentials: + raise ValueError( + "client_options.api_key and credentials are mutually exclusive" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + transport_provided = isinstance(transport, ReservationServiceTransport) + if transport_provided: + # transport is a ReservationServiceTransport instance. + if ( + credentials + or self._client_options.credentials_file + or api_key_value + ): + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if self._client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = cast(ReservationServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ReservationServiceClient._get_api_endpoint( + self._client_options.api_endpoint, + self._client_cert_source, + self._universe_domain, + self._use_mtls_endpoint, + ) + ) + + if not transport_provided: + import google.auth._default # type: ignore + + if api_key_value and hasattr( + google.auth._default, "get_api_key_credentials" + ): + credentials = google.auth._default.get_api_key_credentials( + api_key_value + ) + + transport_init: Union[ + Type[ReservationServiceTransport], + Callable[..., ReservationServiceTransport], + ] = ( + ReservationServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., ReservationServiceTransport], transport) + ) + # initialize with the provided callable or the passed in class + self._transport = transport_init( + credentials=credentials, + credentials_file=self._client_options.credentials_file, + host=self._api_endpoint, + scopes=self._client_options.scopes, + client_cert_source_for_mtls=self._client_cert_source, + quota_project_id=self._client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + api_audience=self._client_options.api_audience, + ) + + if "async" not in str(self._transport): + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ): # pragma: NO COVER + _LOGGER.debug( + "Created client `google.ads.googleads.v23.services.ReservationServiceClient`.", + extra=( + { + "serviceName": "google.ads.googleads.v23.services.ReservationService", + "universeDomain": getattr( + self._transport._credentials, + "universe_domain", + "", + ), + "credentialsType": f"{type(self._transport._credentials).__module__}.{type(self._transport._credentials).__qualname__}", + "credentialsInfo": getattr( + self.transport._credentials, + "get_cred_info", + lambda: None, + )(), + } + if hasattr(self._transport, "_credentials") + else { + "serviceName": "google.ads.googleads.v23.services.ReservationService", + "credentialsType": None, + } + ), + ) + + def quote_campaigns( + self, + request: Optional[ + Union[reservation_service.QuoteCampaignsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reservation_service.QuoteCampaignsResponse: + r"""Proposes quotes for booking campaigns. + This request can have a latency of 30 seconds. + + Args: + request (Union[google.ads.googleads.v23.services.types.QuoteCampaignsRequest, dict]): + The request object. Request message for + [ReservationService.QuoteCampaigns][google.ads.googleads.v23.services.ReservationService.QuoteCampaigns]. + customer_id (str): + Required. The ID of the customer + making the request. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.ads.googleads.v23.services.types.QuoteCampaignsResponse: + Response message for + [ReservationService.QuoteCampaigns][google.ads.googleads.v23.services.ReservationService.QuoteCampaigns]. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [customer_id] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, reservation_service.QuoteCampaignsRequest): + request = reservation_service.QuoteCampaignsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.quote_campaigns] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def book_campaigns( + self, + request: Optional[ + Union[reservation_service.BookCampaignsRequest, dict] + ] = None, + *, + customer_id: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reservation_service.BookCampaignsResponse: + r"""Books the requested campaigns. + This request can have a latency of 30 seconds. + + Args: + request (Union[google.ads.googleads.v23.services.types.BookCampaignsRequest, dict]): + The request object. Request message for + [ReservationService.BookCampaigns][google.ads.googleads.v23.services.ReservationService.BookCampaigns]. + customer_id (str): + Required. The ID of the customer + making the request. + + This corresponds to the ``customer_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.ads.googleads.v23.services.types.BookCampaignsResponse: + Response message for + [ReservationService.BookCampaigns][google.ads.googleads.v23.services.ReservationService.BookCampaigns]. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [customer_id] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, reservation_service.BookCampaignsRequest): + request = reservation_service.BookCampaignsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if customer_id is not None: + request.customer_id = customer_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.book_campaigns] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("customer_id", request.customer_id),) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def __enter__(self) -> "ReservationServiceClient": + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + +__all__ = ("ReservationServiceClient",) diff --git a/google/ads/googleads/v23/services/services/reservation_service/transports/README.rst b/google/ads/googleads/v23/services/services/reservation_service/transports/README.rst new file mode 100644 index 000000000..b69ca178e --- /dev/null +++ b/google/ads/googleads/v23/services/services/reservation_service/transports/README.rst @@ -0,0 +1,9 @@ + +transport inheritance structure +_______________________________ + +`ReservationServiceTransport` is the ABC for all transports. +- public child `ReservationServiceGrpcTransport` for sync gRPC transport (defined in `grpc.py`). +- public child `ReservationServiceGrpcAsyncIOTransport` for async gRPC transport (defined in `grpc_asyncio.py`). +- private child `_BaseReservationServiceRestTransport` for base REST transport with inner classes `_BaseMETHOD` (defined in `rest_base.py`). +- public child `ReservationServiceRestTransport` for sync REST transport with inner classes `METHOD` derived from the parent's corresponding `_BaseMETHOD` classes (defined in `rest.py`). diff --git a/google/ads/googleads/v23/services/services/reservation_service/transports/__init__.py b/google/ads/googleads/v23/services/services/reservation_service/transports/__init__.py new file mode 100644 index 000000000..11395b903 --- /dev/null +++ b/google/ads/googleads/v23/services/services/reservation_service/transports/__init__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict + +from .base import ReservationServiceTransport +from .grpc import ReservationServiceGrpcTransport +from .grpc_asyncio import ReservationServiceGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[ReservationServiceTransport]] +_transport_registry["grpc"] = ReservationServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ReservationServiceGrpcAsyncIOTransport + +__all__ = ( + "ReservationServiceTransport", + "ReservationServiceGrpcTransport", + "ReservationServiceGrpcAsyncIOTransport", +) diff --git a/google/ads/googleads/v23/services/services/reservation_service/transports/base.py b/google/ads/googleads/v23/services/services/reservation_service/transports/base.py new file mode 100644 index 000000000..1a270823a --- /dev/null +++ b/google/ads/googleads/v23/services/services/reservation_service/transports/base.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import abc +from typing import Awaitable, Callable, Optional, Sequence, Union + +from google.ads.googleads.v23 import gapic_version as package_version + +import google.auth # type: ignore +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore +import google.protobuf + +from google.ads.googleads.v23.services.types import reservation_service + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + + +class ReservationServiceTransport(abc.ABC): + """Abstract transport class for ReservationService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/adwords",) + + DEFAULT_HOST: str = "googleads.googleapis.com" + + def __init__( + self, + *, + host: str = DEFAULT_HOST, + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'googleads.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. This argument will be + removed in the next major version of this library. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + **scopes_kwargs, + quota_project_id=quota_project_id, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr( + service_account.Credentials, "with_always_use_jwt_access" + ) + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.quote_campaigns: gapic_v1.method.wrap_method( + self.quote_campaigns, + default_timeout=None, + client_info=client_info, + ), + self.book_campaigns: gapic_v1.method.wrap_method( + self.book_campaigns, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def quote_campaigns( + self, + ) -> Callable[ + [reservation_service.QuoteCampaignsRequest], + Union[ + reservation_service.QuoteCampaignsResponse, + Awaitable[reservation_service.QuoteCampaignsResponse], + ], + ]: + raise NotImplementedError() + + @property + def book_campaigns( + self, + ) -> Callable[ + [reservation_service.BookCampaignsRequest], + Union[ + reservation_service.BookCampaignsResponse, + Awaitable[reservation_service.BookCampaignsResponse], + ], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ReservationServiceTransport",) diff --git a/google/ads/googleads/v23/services/services/reservation_service/transports/grpc.py b/google/ads/googleads/v23/services/services/reservation_service/transports/grpc.py new file mode 100644 index 000000000..97eabdf22 --- /dev/null +++ b/google/ads/googleads/v23/services/services/reservation_service/transports/grpc.py @@ -0,0 +1,413 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import logging as std_logging +import pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import grpc_helpers +from google.api_core import gapic_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore + +from google.ads.googleads.v23.services.types import reservation_service +from .base import ReservationServiceTransport, DEFAULT_CLIENT_INFO + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + + +class _LoggingClientInterceptor( + grpc.UnaryUnaryClientInterceptor +): # pragma: NO COVER + def intercept_unary_unary(self, continuation, client_call_details, request): + logging_enabled = CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ) + if logging_enabled: # pragma: NO COVER + request_metadata = client_call_details.metadata + if isinstance(request, proto.Message): + request_payload = type(request).to_json(request) + elif isinstance(request, google.protobuf.message.Message): + request_payload = MessageToJson(request) + else: + request_payload = ( + f"{type(request).__name__}: {pickle.dumps(request)}" + ) + + request_metadata = { + key: ( + value.decode("utf-8") if isinstance(value, bytes) else value + ) + for key, value in request_metadata + } + grpc_request = { + "payload": request_payload, + "requestMethod": "grpc", + "metadata": dict(request_metadata), + } + _LOGGER.debug( + f"Sending request for {client_call_details.method}", + extra={ + "serviceName": "google.ads.googleads.v23.services.ReservationService", + "rpcName": str(client_call_details.method), + "request": grpc_request, + "metadata": grpc_request["metadata"], + }, + ) + response = continuation(client_call_details, request) + if logging_enabled: # pragma: NO COVER + response_metadata = response.trailing_metadata() + # Convert gRPC metadata `` to list of tuples + metadata = ( + dict([(k, str(v)) for k, v in response_metadata]) + if response_metadata + else None + ) + result = response.result() + if isinstance(result, proto.Message): + response_payload = type(result).to_json(result) + elif isinstance(result, google.protobuf.message.Message): + response_payload = MessageToJson(result) + else: + response_payload = ( + f"{type(result).__name__}: {pickle.dumps(result)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v23.services.ReservationService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ReservationServiceGrpcTransport(ReservationServiceTransport): + """gRPC backend transport for ReservationService. + + Service for reservation related operations. + This service is not publicly available. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _stubs: Dict[str, Callable] + + def __init__( + self, + *, + host: str = "googleads.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[ + Union[grpc.Channel, Callable[..., grpc.Channel]] + ] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[ + Callable[[], Tuple[bytes, bytes]] + ] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'googleads.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if a ``channel`` instance is provided. + credentials_file (Optional[str]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + This argument will be removed in the next major version of this library. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if a ``channel`` instance is provided. + channel (Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if isinstance(channel, grpc.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + self._interceptor = _LoggingClientInterceptor() + self._logged_channel = grpc.intercept_channel( + self._grpc_channel, self._interceptor + ) + + # Wrap messages. This must be done after self._logged_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "googleads.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> grpc.Channel: + """Create and return a gRPC channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. This argument will be + removed in the next major version of this library. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def quote_campaigns( + self, + ) -> Callable[ + [reservation_service.QuoteCampaignsRequest], + reservation_service.QuoteCampaignsResponse, + ]: + r"""Return a callable for the quote campaigns method over gRPC. + + Proposes quotes for booking campaigns. + This request can have a latency of 30 seconds. + + Returns: + Callable[[~.QuoteCampaignsRequest], + ~.QuoteCampaignsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "quote_campaigns" not in self._stubs: + self._stubs["quote_campaigns"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v23.services.ReservationService/QuoteCampaigns", + request_serializer=reservation_service.QuoteCampaignsRequest.serialize, + response_deserializer=reservation_service.QuoteCampaignsResponse.deserialize, + ) + return self._stubs["quote_campaigns"] + + @property + def book_campaigns( + self, + ) -> Callable[ + [reservation_service.BookCampaignsRequest], + reservation_service.BookCampaignsResponse, + ]: + r"""Return a callable for the book campaigns method over gRPC. + + Books the requested campaigns. + This request can have a latency of 30 seconds. + + Returns: + Callable[[~.BookCampaignsRequest], + ~.BookCampaignsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "book_campaigns" not in self._stubs: + self._stubs["book_campaigns"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v23.services.ReservationService/BookCampaigns", + request_serializer=reservation_service.BookCampaignsRequest.serialize, + response_deserializer=reservation_service.BookCampaignsResponse.deserialize, + ) + return self._stubs["book_campaigns"] + + def close(self): + self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ReservationServiceGrpcTransport",) diff --git a/google/ads/googleads/v23/services/services/reservation_service/transports/grpc_asyncio.py b/google/ads/googleads/v23/services/services/reservation_service/transports/grpc_asyncio.py new file mode 100644 index 000000000..80c74f45a --- /dev/null +++ b/google/ads/googleads/v23/services/services/reservation_service/transports/grpc_asyncio.py @@ -0,0 +1,439 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import inspect +import pickle +import logging as std_logging +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1 +from google.api_core import grpc_helpers_async +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.protobuf.json_format import MessageToJson +import google.protobuf.message + +import grpc # type: ignore +import proto # type: ignore +from grpc.experimental import aio # type: ignore + +from google.ads.googleads.v23.services.types import reservation_service +from .base import ReservationServiceTransport, DEFAULT_CLIENT_INFO + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + + +class _LoggingClientAIOInterceptor( + grpc.aio.UnaryUnaryClientInterceptor +): # pragma: NO COVER + async def intercept_unary_unary( + self, continuation, client_call_details, request + ): + logging_enabled = CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ) + if logging_enabled: # pragma: NO COVER + request_metadata = client_call_details.metadata + if isinstance(request, proto.Message): + request_payload = type(request).to_json(request) + elif isinstance(request, google.protobuf.message.Message): + request_payload = MessageToJson(request) + else: + request_payload = ( + f"{type(request).__name__}: {pickle.dumps(request)}" + ) + + request_metadata = { + key: ( + value.decode("utf-8") if isinstance(value, bytes) else value + ) + for key, value in request_metadata + } + grpc_request = { + "payload": request_payload, + "requestMethod": "grpc", + "metadata": dict(request_metadata), + } + _LOGGER.debug( + f"Sending request for {client_call_details.method}", + extra={ + "serviceName": "google.ads.googleads.v23.services.ReservationService", + "rpcName": str(client_call_details.method), + "request": grpc_request, + "metadata": grpc_request["metadata"], + }, + ) + response = await continuation(client_call_details, request) + if logging_enabled: # pragma: NO COVER + response_metadata = await response.trailing_metadata() + # Convert gRPC metadata `` to list of tuples + metadata = ( + dict([(k, str(v)) for k, v in response_metadata]) + if response_metadata + else None + ) + result = await response + if isinstance(result, proto.Message): + response_payload = type(result).to_json(result) + elif isinstance(result, google.protobuf.message.Message): + response_payload = MessageToJson(result) + else: + response_payload = ( + f"{type(result).__name__}: {pickle.dumps(result)}" + ) + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.ads.googleads.v23.services.ReservationService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class ReservationServiceGrpcAsyncIOTransport(ReservationServiceTransport): + """gRPC AsyncIO backend transport for ReservationService. + + Service for reservation related operations. + This service is not publicly available. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _grpc_channel: aio.Channel + _stubs: Dict[str, Callable] = {} + + @classmethod + def create_channel( + cls, + host: str = "googleads.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> aio.Channel: + """Create and return a gRPC AsyncIO channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. This argument will be + removed in the next major version of this library. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + aio.Channel: A gRPC AsyncIO channel object. + """ + + return grpc_helpers_async.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + def __init__( + self, + *, + host: str = "googleads.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[ + Union[aio.Channel, Callable[..., aio.Channel]] + ] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[ + Callable[[], Tuple[bytes, bytes]] + ] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'googleads.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if a ``channel`` instance is provided. + credentials_file (Optional[str]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + This argument will be removed in the next major version of this library. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + channel (Optional[Union[aio.Channel, Callable[..., aio.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn( + "client_cert_source is deprecated", DeprecationWarning + ) + + if isinstance(channel, aio.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + else: + self._ssl_channel_credentials = ( + SslCredentials().ssl_credentials + ) + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = ( + grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + self._interceptor = _LoggingClientAIOInterceptor() + self._grpc_channel._unary_unary_interceptors.append(self._interceptor) + self._logged_channel = self._grpc_channel + self._wrap_with_kind = ( + "kind" + in inspect.signature(gapic_v1.method_async.wrap_method).parameters + ) + # Wrap messages. This must be done after self._logged_channel exists + self._prep_wrapped_messages(client_info) + + @property + def grpc_channel(self) -> aio.Channel: + """Create the channel designed to connect to this service. + + This property caches on the instance; repeated calls return + the same channel. + """ + # Return the channel from cache. + return self._grpc_channel + + @property + def quote_campaigns( + self, + ) -> Callable[ + [reservation_service.QuoteCampaignsRequest], + Awaitable[reservation_service.QuoteCampaignsResponse], + ]: + r"""Return a callable for the quote campaigns method over gRPC. + + Proposes quotes for booking campaigns. + This request can have a latency of 30 seconds. + + Returns: + Callable[[~.QuoteCampaignsRequest], + Awaitable[~.QuoteCampaignsResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "quote_campaigns" not in self._stubs: + self._stubs["quote_campaigns"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v23.services.ReservationService/QuoteCampaigns", + request_serializer=reservation_service.QuoteCampaignsRequest.serialize, + response_deserializer=reservation_service.QuoteCampaignsResponse.deserialize, + ) + return self._stubs["quote_campaigns"] + + @property + def book_campaigns( + self, + ) -> Callable[ + [reservation_service.BookCampaignsRequest], + Awaitable[reservation_service.BookCampaignsResponse], + ]: + r"""Return a callable for the book campaigns method over gRPC. + + Books the requested campaigns. + This request can have a latency of 30 seconds. + + Returns: + Callable[[~.BookCampaignsRequest], + Awaitable[~.BookCampaignsResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "book_campaigns" not in self._stubs: + self._stubs["book_campaigns"] = self._logged_channel.unary_unary( + "/google.ads.googleads.v23.services.ReservationService/BookCampaigns", + request_serializer=reservation_service.BookCampaignsRequest.serialize, + response_deserializer=reservation_service.BookCampaignsResponse.deserialize, + ) + return self._stubs["book_campaigns"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.quote_campaigns: self._wrap_method( + self.quote_campaigns, + default_timeout=None, + client_info=client_info, + ), + self.book_campaigns: self._wrap_method( + self.book_campaigns, + default_timeout=None, + client_info=client_info, + ), + } + + def _wrap_method(self, func, *args, **kwargs): + if self._wrap_with_kind: # pragma: NO COVER + kwargs["kind"] = self.kind + return gapic_v1.method_async.wrap_method(func, *args, **kwargs) + + def close(self): + return self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc_asyncio" + + +__all__ = ("ReservationServiceGrpcAsyncIOTransport",) diff --git a/google/ads/googleads/v23/services/types/__init__.py b/google/ads/googleads/v23/services/types/__init__.py index 189d34c6b..449d162f3 100644 --- a/google/ads/googleads/v23/services/types/__init__.py +++ b/google/ads/googleads/v23/services/types/__init__.py @@ -755,6 +755,7 @@ TargetFrequencySettings, Targeting, YouTubeSelectLineUp, + YouTubeSelectLineUpTargeting, YouTubeSelectSettings, ) from .recommendation_service import ( @@ -779,6 +780,12 @@ MutateRemarketingActionsResponse, RemarketingActionOperation, ) +from .reservation_service import ( + BookCampaignsRequest, + BookCampaignsResponse, + QuoteCampaignsRequest, + QuoteCampaignsResponse, +) from .shareable_preview_service import ( AssetGroupIdentifier, GenerateShareablePreviewsRequest, @@ -786,6 +793,7 @@ ShareablePreview, ShareablePreviewOrError, ShareablePreviewResult, + YouTubeLivePreviewResult, ) from .shared_criterion_service import ( MutateSharedCriteriaRequest, @@ -1410,6 +1418,7 @@ "TargetFrequencySettings", "Targeting", "YouTubeSelectLineUp", + "YouTubeSelectLineUpTargeting", "YouTubeSelectSettings", "ApplyRecommendationOperation", "ApplyRecommendationRequest", @@ -1427,12 +1436,17 @@ "MutateRemarketingActionsRequest", "MutateRemarketingActionsResponse", "RemarketingActionOperation", + "BookCampaignsRequest", + "BookCampaignsResponse", + "QuoteCampaignsRequest", + "QuoteCampaignsResponse", "AssetGroupIdentifier", "GenerateShareablePreviewsRequest", "GenerateShareablePreviewsResponse", "ShareablePreview", "ShareablePreviewOrError", "ShareablePreviewResult", + "YouTubeLivePreviewResult", "MutateSharedCriteriaRequest", "MutateSharedCriteriaResponse", "MutateSharedCriterionResult", diff --git a/google/ads/googleads/v23/services/types/benchmarks_service.py b/google/ads/googleads/v23/services/types/benchmarks_service.py index 6014e8116..6f4d2e812 100644 --- a/google/ads/googleads/v23/services/types/benchmarks_service.py +++ b/google/ads/googleads/v23/services/types/benchmarks_service.py @@ -525,15 +525,18 @@ class BreakdownDefinition(proto.Message): Attributes: date_breakdown (google.ads.googleads.v23.enums.types.BenchmarksTimeGranularityEnum.BenchmarksTimeGranularity): - A date breakdown using the selected - granularity. The effective date range is - extended to include the full time periods that - overlap with the selected start and end dates. - For example, a monthly breakdown with a start - date of 2025-06-15 will include a breakdown for - June. Weeks start on Sunday and end on Saturday. - This is different from the ISO 8601 standard, - where weeks start on Monday. + The granularity for segmenting metrics by date. When this + field is set, a valid date_range in the + GenerateBenchmarksMetricsRequest is required and must + precisely align with the boundaries of the selected + granularity. + + For example, a monthly breakdown must start on the first day + of a month and end on the last day of a month. A quarterly + breakdown must start on the first day of a quarter and end + on the last day of a quarter. A weekly breakdown must start + on a Sunday and end on a Saturday. This is different from + the ISO 8601 standard, where weeks start on Monday. """ date_breakdown: ( diff --git a/google/ads/googleads/v23/services/types/content_creator_insights_service.py b/google/ads/googleads/v23/services/types/content_creator_insights_service.py index fc259d2a8..9253fe66c 100644 --- a/google/ads/googleads/v23/services/types/content_creator_insights_service.py +++ b/google/ads/googleads/v23/services/types/content_creator_insights_service.py @@ -23,6 +23,7 @@ from google.ads.googleads.v23.common.types import audience_insights_attribute from google.ads.googleads.v23.common.types import criteria from google.ads.googleads.v23.enums.types import insights_trend +from google.ads.googleads.v23.enums.types import partnership_opportunity __protobuf__ = proto.module( @@ -109,7 +110,28 @@ class SearchAttributes(proto.Message): viewers match the input audience. Attributes age_range, gender, user_interest, entity, category, device, parental_status, and income_range are supported. Attribute - location is not supported. + location is not supported. Attributes user_interest, entity, + and category can only be set in audience_attributes when + audience_combinations is unused. + audience_combinations (MutableSequence[google.ads.googleads.v23.common.types.InsightsAudienceAttributeGroup]): + Optional. A list of audience attribute groups consisting of + one or more Knowledge Graph entities, Product & Service + Categories and user interests that describes an audience. + The groups have a logical AND-of-ORs structure: + + 1. Attributes within each InsightsAudienceAttributeGroup are + combined with OR. + + 2. The groups themselves are combined together with AND. + + For example, an audience (Interest A OR Interest B) AND + (Entity C) is represented using two groups. The first group + contains the two interests and the second group contains the + entity. + + This field cannot be set if any Knowledge Graph entities, + Product & Service Categories, or user interests are + specified in audience_attributes. creator_attributes (MutableSequence[google.ads.googleads.v23.common.types.AudienceInsightsAttribute]): Optional. Creator attributes that describe a collection of types of content. This is used to search for creators whose @@ -129,6 +151,13 @@ class SearchAttributes(proto.Message): number=1, message=audience_insights_attribute.AudienceInsightsAttribute, ) + audience_combinations: MutableSequence[ + audience_insights_attribute.InsightsAudienceAttributeGroup + ] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=audience_insights_attribute.InsightsAudienceAttributeGroup, + ) creator_attributes: MutableSequence[ audience_insights_attribute.AudienceInsightsAttribute ] = proto.RepeatedField( @@ -415,6 +444,9 @@ class YouTubeMetrics(proto.Message): See https://support.google.com/google-ads/answer/13828964 for more information about BrandConnect. + partnership_opportunities (MutableSequence[google.ads.googleads.v23.enums.types.PartnershipOpportunityEnum.PartnershipOpportunity]): + Partnership opportunities available for this + creator. """ subscriber_count: int = proto.Field( @@ -481,6 +513,13 @@ class YouTubeMetrics(proto.Message): proto.BOOL, number=15, ) + partnership_opportunities: MutableSequence[ + partnership_opportunity.PartnershipOpportunityEnum.PartnershipOpportunity + ] = proto.RepeatedField( + proto.ENUM, + number=17, + enum=partnership_opportunity.PartnershipOpportunityEnum.PartnershipOpportunity, + ) class YouTubeChannelInsights(proto.Message): @@ -622,9 +661,32 @@ class SearchAudience(proto.Message): Attributes: audience_attributes (MutableSequence[google.ads.googleads.v23.common.types.AudienceInsightsAttribute]): - Required. Audience attributes that describe - an audience of viewers. This is used to search - for topics trending for the defined audience. + Required. Audience attributes that describe an audience of + viewers. This is used to search for topics trending for the + defined audience. Attributes age_range, gender, + user_interest, entity, category, parental_status, and + income_range are supported. Attributes user_interest, + entity, and category can only be set in audience_attributes + when audience_combinations is unused. + audience_combinations (MutableSequence[google.ads.googleads.v23.common.types.InsightsAudienceAttributeGroup]): + Optional. A list of audience attribute groups consisting of + one or more Knowledge Graph entities, Product & Service + Categories and user interests that describes an audience. + The groups have a logical AND-of-ORs structure: + + 1. Attributes within each InsightsAudienceAttributeGroup are + combined with OR. + + 2. The groups themselves are combined together with AND. + + For example, an audience (Interest A OR Interest B) AND + (Entity C) is represented using two groups. The first group + contains the two interests and the second group contains the + entity. + + This field cannot be set if any Knowledge Graph entities, + Product & Service Categories, or user interests are + specified in audience_attributes. """ audience_attributes: MutableSequence[ @@ -634,6 +696,13 @@ class SearchAudience(proto.Message): number=1, message=audience_insights_attribute.AudienceInsightsAttribute, ) + audience_combinations: MutableSequence[ + audience_insights_attribute.InsightsAudienceAttributeGroup + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=audience_insights_attribute.InsightsAudienceAttributeGroup, + ) class SearchTopics(proto.Message): @@ -670,14 +739,15 @@ class TrendInsight(proto.Message): metrics are for the latest available month and the comparison period is 3 months. trend (google.ads.googleads.v23.enums.types.InsightsTrendEnum.InsightsTrend): - The direction of trend (such as RISING or - DECLINING). + Indicate if a trend is sustained or emerging. Use + trend_metrics.trend_change_percent to determine the + direction of the trend. trend_data_points (MutableSequence[google.ads.googleads.v23.services.types.TrendInsightDataPoint]): - 12 months of historical data for the trend, including the - most recent month the TrendInsight represents. Each data - point represents 1 month of data and the comparison period - is 1 month. The data points are ordered from most recent - month to least recent month. Only populated for trends using + 3 years of historical data for the trend, including the most + recent month the TrendInsight represents. Each data point + represents 1 month of data and the comparison period is 1 + month. The data points are ordered from most recent month to + least recent month. Only populated for trends using search_topics. related_videos (MutableSequence[google.ads.googleads.v23.common.types.AudienceInsightsAttributeMetadata]): Related videos for this topic. Only populated for trends diff --git a/google/ads/googleads/v23/services/types/google_ads_service.py b/google/ads/googleads/v23/services/types/google_ads_service.py index 6baf2c714..b07d2137f 100644 --- a/google/ads/googleads/v23/services/types/google_ads_service.py +++ b/google/ads/googleads/v23/services/types/google_ads_service.py @@ -19,6 +19,8 @@ import proto # type: ignore +from google.ads.googleads.v23.actions.types import book_campaigns +from google.ads.googleads.v23.actions.types import quote_campaigns from google.ads.googleads.v23.common.types import metrics as gagc_metrics from google.ads.googleads.v23.common.types import segments as gagc_segments from google.ads.googleads.v23.enums.types import ( @@ -107,6 +109,9 @@ from google.ads.googleads.v23.resources.types import ( android_privacy_shared_key_google_network_type as gagr_android_privacy_shared_key_google_network_type, ) +from google.ads.googleads.v23.resources.types import ( + app_top_combination_view as gagr_app_top_combination_view, +) from google.ads.googleads.v23.resources.types import ( applied_incentive as gagr_applied_incentive, ) @@ -530,6 +535,9 @@ user_location_view as gagr_user_location_view, ) from google.ads.googleads.v23.resources.types import video as gagr_video +from google.ads.googleads.v23.resources.types import ( + video_enhancement as gagr_video_enhancement, +) from google.ads.googleads.v23.resources.types import ( webpage_view as gagr_webpage_view, ) @@ -905,6 +913,8 @@ class GoogleAdsRow(proto.Message): ad_group_ad_asset_combination_view (google.ads.googleads.v23.resources.types.AdGroupAdAssetCombinationView): The ad group ad asset combination view in the query. + app_top_combination_view (google.ads.googleads.v23.resources.types.AppTopCombinationView): + The app top combination view in the query. ad_group_ad_asset_view (google.ads.googleads.v23.resources.types.AdGroupAdAssetView): The ad group ad asset view in the query. ad_group_ad_label (google.ads.googleads.v23.resources.types.AdGroupAdLabel): @@ -1328,6 +1338,9 @@ class GoogleAdsRow(proto.Message): The topic constant referenced in the query. video (google.ads.googleads.v23.resources.types.Video): The video referenced in the query. + video_enhancement (google.ads.googleads.v23.resources.types.VideoEnhancement): + The video enhancement referenced in the + query. webpage_view (google.ads.googleads.v23.resources.types.WebpageView): The webpage view referenced in the query. lead_form_submission_data (google.ads.googleads.v23.resources.types.LeadFormSubmissionData): @@ -1399,6 +1412,13 @@ class GoogleAdsRow(proto.Message): number=193, message=gagr_ad_group_ad_asset_combination_view.AdGroupAdAssetCombinationView, ) + app_top_combination_view: ( + gagr_app_top_combination_view.AppTopCombinationView + ) = proto.Field( + proto.MESSAGE, + number=247, + message=gagr_app_top_combination_view.AppTopCombinationView, + ) ad_group_ad_asset_view: gagr_ad_group_ad_asset_view.AdGroupAdAssetView = ( proto.Field( proto.MESSAGE, @@ -2392,6 +2412,11 @@ class GoogleAdsRow(proto.Message): number=39, message=gagr_video.Video, ) + video_enhancement: gagr_video_enhancement.VideoEnhancement = proto.Field( + proto.MESSAGE, + number=250, + message=gagr_video_enhancement.VideoEnhancement, + ) webpage_view: gagr_webpage_view.WebpageView = proto.Field( proto.MESSAGE, number=162, @@ -2482,7 +2507,8 @@ class MutateGoogleAdsRequest(proto.Message): all valid. Default is false. validate_only (bool): If true, the request is validated but not - executed. Only errors are returned, not results. + executed. Mutates only return errors, not + results. Actions return results and errors. response_content_type (google.ads.googleads.v23.enums.types.ResponseContentTypeEnum.ResponseContentType): The response content type setting. Determines whether the mutable resource or just the @@ -2548,7 +2574,8 @@ class MutateGoogleAdsResponse(proto.Message): class MutateOperation(proto.Message): - r"""A single operation (create, update, remove) on a resource. + r"""A single operation (create, update, remove) on a resource, or + execute an action. This message has `oneof`_ fields (mutually exclusive fields). For each oneof, at most one member field can be set at the same time. @@ -2652,6 +2679,10 @@ class MutateOperation(proto.Message): bidding_strategy_operation (google.ads.googleads.v23.services.types.BiddingStrategyOperation): A bidding strategy mutate operation. + This field is a member of `oneof`_ ``operation``. + book_campaigns_operation (google.ads.googleads.v23.actions.types.BookCampaignsOperation): + Request message for the BookCampaigns action. + This field is a member of `oneof`_ ``operation``. campaign_asset_operation (google.ads.googleads.v23.services.types.CampaignAssetOperation): A campaign asset mutate operation. @@ -2787,6 +2818,11 @@ class MutateOperation(proto.Message): label_operation (google.ads.googleads.v23.services.types.LabelOperation): A label mutate operation. + This field is a member of `oneof`_ ``operation``. + quote_campaigns_operation (google.ads.googleads.v23.actions.types.QuoteCampaignsOperation): + Request message for the QuoteCampaigns action. Requests + using this operation must set validate_only to true. + This field is a member of `oneof`_ ``operation``. recommendation_subscription_operation (google.ads.googleads.v23.services.types.RecommendationSubscriptionOperation): A recommendation subscription mutate @@ -2987,6 +3023,14 @@ class MutateOperation(proto.Message): oneof="operation", message=bidding_strategy_service.BiddingStrategyOperation, ) + book_campaigns_operation: book_campaigns.BookCampaignsOperation = ( + proto.Field( + proto.MESSAGE, + number=89, + oneof="operation", + message=book_campaigns.BookCampaignsOperation, + ) + ) campaign_asset_operation: campaign_asset_service.CampaignAssetOperation = ( proto.Field( proto.MESSAGE, @@ -3243,6 +3287,14 @@ class MutateOperation(proto.Message): oneof="operation", message=label_service.LabelOperation, ) + quote_campaigns_operation: quote_campaigns.QuoteCampaignsOperation = ( + proto.Field( + proto.MESSAGE, + number=88, + oneof="operation", + message=quote_campaigns.QuoteCampaignsOperation, + ) + ) recommendation_subscription_operation: ( recommendation_subscription_service.RecommendationSubscriptionOperation ) = proto.Field( @@ -3290,7 +3342,7 @@ class MutateOperation(proto.Message): class MutateOperationResponse(proto.Message): - r"""Response message for the resource mutate. + r"""Response message for the resource mutate or action. This message has `oneof`_ fields (mutually exclusive fields). For each oneof, at most one member field can be set at the same time. @@ -3398,6 +3450,10 @@ class MutateOperationResponse(proto.Message): bidding_strategy_result (google.ads.googleads.v23.services.types.MutateBiddingStrategyResult): The result for the bidding strategy mutate. + This field is a member of `oneof`_ ``response``. + book_campaigns_result (google.ads.googleads.v23.actions.types.BookCampaignsResult): + The result for the BookCampaigns action. + This field is a member of `oneof`_ ``response``. campaign_asset_result (google.ads.googleads.v23.services.types.MutateCampaignAssetResult): The result for the campaign asset mutate. @@ -3547,6 +3603,10 @@ class MutateOperationResponse(proto.Message): label_result (google.ads.googleads.v23.services.types.MutateLabelResult): The result for the label mutate. + This field is a member of `oneof`_ ``response``. + quote_campaigns_result (google.ads.googleads.v23.actions.types.QuoteCampaignsResult): + The result for the QuoteCampaigns action. + This field is a member of `oneof`_ ``response``. recommendation_subscription_result (google.ads.googleads.v23.services.types.MutateRecommendationSubscriptionResult): The result for the recommendation @@ -3748,6 +3808,12 @@ class MutateOperationResponse(proto.Message): oneof="response", message=bidding_strategy_service.MutateBiddingStrategyResult, ) + book_campaigns_result: book_campaigns.BookCampaignsResult = proto.Field( + proto.MESSAGE, + number=89, + oneof="response", + message=book_campaigns.BookCampaignsResult, + ) campaign_asset_result: campaign_asset_service.MutateCampaignAssetResult = ( proto.Field( proto.MESSAGE, @@ -4004,6 +4070,12 @@ class MutateOperationResponse(proto.Message): oneof="response", message=label_service.MutateLabelResult, ) + quote_campaigns_result: quote_campaigns.QuoteCampaignsResult = proto.Field( + proto.MESSAGE, + number=88, + oneof="response", + message=quote_campaigns.QuoteCampaignsResult, + ) recommendation_subscription_result: ( recommendation_subscription_service.MutateRecommendationSubscriptionResult ) = proto.Field( diff --git a/google/ads/googleads/v23/services/types/reach_plan_service.py b/google/ads/googleads/v23/services/types/reach_plan_service.py index 1a7302109..995f3d64b 100644 --- a/google/ads/googleads/v23/services/types/reach_plan_service.py +++ b/google/ads/googleads/v23/services/types/reach_plan_service.py @@ -82,6 +82,7 @@ "AdvancedProductTargeting", "YouTubeSelectSettings", "YouTubeSelectLineUp", + "YouTubeSelectLineUpTargeting", "SurfaceTargetingCombinations", "SurfaceTargeting", "TargetFrequencySettings", @@ -520,8 +521,14 @@ class PlannableTargeting(proto.Message): networks (MutableSequence[google.ads.googleads.v23.enums.types.ReachPlanNetworkEnum.ReachPlanNetwork]): Targetable networks for the ad product. youtube_select_lineups (MutableSequence[google.ads.googleads.v23.services.types.YouTubeSelectLineUp]): - Targetable YouTube Select Lineups for the ad - product. + Targetable YouTube Select Lineups for the ad product. This + field is deprecated in V23_2 and will eventually be removed. + Use youtube_select_lineup_targeting instead. + youtube_select_lineup_targeting (google.ads.googleads.v23.services.types.YouTubeSelectLineUpTargeting): + Targetable YouTube Select Lineups for the ad product. + + This field replaces the deprecated youtube_select_lineups + field. surface_targeting (google.ads.googleads.v23.services.types.SurfaceTargetingCombinations): Targetable surface combinations for the ad product. @@ -558,6 +565,13 @@ class PlannableTargeting(proto.Message): message="YouTubeSelectLineUp", ) ) + youtube_select_lineup_targeting: "YouTubeSelectLineUpTargeting" = ( + proto.Field( + proto.MESSAGE, + number=7, + message="YouTubeSelectLineUpTargeting", + ) + ) surface_targeting: "SurfaceTargetingCombinations" = proto.Field( proto.MESSAGE, number=6, @@ -1238,6 +1252,16 @@ class Forecast(proto.Message): for more information on TrueView Views. This field is a member of `oneof`_ ``_trueview_views``. + clicks (int): + The number of clicks, which is the main user + action associated with an ad format of bid type + CPC (Cost-Per-Click). + + See + https://support.google.com/google-ads/answer/31799 + for more information on clicks. + + This field is a member of `oneof`_ ``_clicks``. """ on_target_reach: int = proto.Field( @@ -1302,6 +1326,11 @@ class Forecast(proto.Message): number=17, optional=True, ) + clicks: int = proto.Field( + proto.INT64, + number=18, + optional=True, + ) class PlannedProductReachForecast(proto.Message): @@ -1429,6 +1458,16 @@ class PlannedProductForecast(proto.Message): for more information on TrueView Views. This field is a member of `oneof`_ ``_trueview_views``. + clicks (int): + The number of clicks, which is the main user + action associated with an ad format of bid type + CPC (Cost-Per-Click). + + See + https://support.google.com/google-ads/answer/31799 + for more information on clicks. + + This field is a member of `oneof`_ ``_clicks``. """ on_target_reach: int = proto.Field( @@ -1487,6 +1526,11 @@ class PlannedProductForecast(proto.Message): number=13, optional=True, ) + clicks: int = proto.Field( + proto.INT64, + number=14, + optional=True, + ) class OnTargetAudienceMetrics(proto.Message): @@ -1702,6 +1746,33 @@ class YouTubeSelectLineUp(proto.Message): ) +class YouTubeSelectLineUpTargeting(proto.Message): + r"""Targetable YouTube Select Lineups for the ad product and the + default Lineup. + + Attributes: + youtube_select_lineups (MutableSequence[google.ads.googleads.v23.services.types.YouTubeSelectLineUp]): + Targetable YouTube Select Lineups for the ad + product. + default_youtube_select_lineup (google.ads.googleads.v23.services.types.YouTubeSelectLineUp): + The default YouTube Select Lineup for the ad + product if available. + """ + + youtube_select_lineups: MutableSequence["YouTubeSelectLineUp"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="YouTubeSelectLineUp", + ) + ) + default_youtube_select_lineup: "YouTubeSelectLineUp" = proto.Field( + proto.MESSAGE, + number=2, + message="YouTubeSelectLineUp", + ) + + class SurfaceTargetingCombinations(proto.Message): r"""The surface targeting combinations available for an ad product. diff --git a/google/ads/googleads/v23/services/types/reservation_service.py b/google/ads/googleads/v23/services/types/reservation_service.py new file mode 100644 index 000000000..3d7758902 --- /dev/null +++ b/google/ads/googleads/v23/services/types/reservation_service.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + + +import proto # type: ignore + +from google.ads.googleads.v23.actions.types import book_campaigns +from google.ads.googleads.v23.actions.types import quote_campaigns + + +__protobuf__ = proto.module( + package="google.ads.googleads.v23.services", + marshal="google.ads.googleads.v23", + manifest={ + "QuoteCampaignsRequest", + "QuoteCampaignsResponse", + "BookCampaignsRequest", + "BookCampaignsResponse", + }, +) + + +class QuoteCampaignsRequest(proto.Message): + r"""Request message for + [ReservationService.QuoteCampaigns][google.ads.googleads.v23.services.ReservationService.QuoteCampaigns]. + + Attributes: + customer_id (str): + Required. The ID of the customer making the + request. + operation (google.ads.googleads.v23.actions.types.QuoteCampaignsOperation): + The operation to quote the campaigns. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: quote_campaigns.QuoteCampaignsOperation = proto.Field( + proto.MESSAGE, + number=2, + message=quote_campaigns.QuoteCampaignsOperation, + ) + + +class QuoteCampaignsResponse(proto.Message): + r"""Response message for + [ReservationService.QuoteCampaigns][google.ads.googleads.v23.services.ReservationService.QuoteCampaigns]. + + Attributes: + result (google.ads.googleads.v23.actions.types.QuoteCampaignsResult): + The result of the quote campaigns operation. + """ + + result: quote_campaigns.QuoteCampaignsResult = proto.Field( + proto.MESSAGE, + number=1, + message=quote_campaigns.QuoteCampaignsResult, + ) + + +class BookCampaignsRequest(proto.Message): + r"""Request message for + [ReservationService.BookCampaigns][google.ads.googleads.v23.services.ReservationService.BookCampaigns]. + + Attributes: + customer_id (str): + Required. The ID of the customer making the + request. + operation (google.ads.googleads.v23.actions.types.BookCampaignsOperation): + The operation to book the campaigns. + """ + + customer_id: str = proto.Field( + proto.STRING, + number=1, + ) + operation: book_campaigns.BookCampaignsOperation = proto.Field( + proto.MESSAGE, + number=2, + message=book_campaigns.BookCampaignsOperation, + ) + + +class BookCampaignsResponse(proto.Message): + r"""Response message for + [ReservationService.BookCampaigns][google.ads.googleads.v23.services.ReservationService.BookCampaigns]. + + Attributes: + result (google.ads.googleads.v23.actions.types.BookCampaignsResult): + The result of the book campaigns operation. + """ + + result: book_campaigns.BookCampaignsResult = proto.Field( + proto.MESSAGE, + number=1, + message=book_campaigns.BookCampaignsResult, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/ads/googleads/v23/services/types/shareable_preview_service.py b/google/ads/googleads/v23/services/types/shareable_preview_service.py index 4dff2814c..852f61903 100644 --- a/google/ads/googleads/v23/services/types/shareable_preview_service.py +++ b/google/ads/googleads/v23/services/types/shareable_preview_service.py @@ -19,6 +19,9 @@ import proto # type: ignore +from google.ads.googleads.v23.enums.types import ( + preview_type as gage_preview_type, +) from google.rpc import status_pb2 # type: ignore @@ -32,6 +35,7 @@ "GenerateShareablePreviewsResponse", "ShareablePreviewOrError", "ShareablePreviewResult", + "YouTubeLivePreviewResult", }, ) @@ -65,10 +69,20 @@ class GenerateShareablePreviewsRequest(proto.Message): class ShareablePreview(proto.Message): r"""A shareable preview with its identifier. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: asset_group_identifier (google.ads.googleads.v23.services.types.AssetGroupIdentifier): - Required. Asset group of the shareable - preview. + Optional. Asset group of the shareable preview. Only + supported for preview type UI_PREVIEW or unset. + preview_type (google.ads.googleads.v23.enums.types.PreviewTypeEnum.PreviewType): + Optional. The type of preview to generate. + ad_group_ad (str): + Ad group ad of the shareable preview. Only supported for + preview type YOUTUBE_LIVE_PREVIEW. Format: + customers/{customer_id}/adGroupAds/{ad_group_id}~{ad_id} + + This field is a member of `oneof`_ ``identifier``. """ asset_group_identifier: "AssetGroupIdentifier" = proto.Field( @@ -76,6 +90,16 @@ class ShareablePreview(proto.Message): number=1, message="AssetGroupIdentifier", ) + preview_type: gage_preview_type.PreviewTypeEnum.PreviewType = proto.Field( + proto.ENUM, + number=3, + enum=gage_preview_type.PreviewTypeEnum.PreviewType, + ) + ad_group_ad: str = proto.Field( + proto.STRING, + number=2, + oneof="identifier", + ) class AssetGroupIdentifier(proto.Message): @@ -129,6 +153,11 @@ class ShareablePreviewOrError(proto.Message): The shareable preview partial failure error. This field is a member of `oneof`_ ``generate_shareable_preview_response``. + ad_group_ad (str): + The ad group ad of the shareable preview. Format: + customers/{customer_id}/adGroupAds/{ad_group_id}~{ad_id} + + This field is a member of `oneof`_ ``identifier``. """ asset_group_identifier: "AssetGroupIdentifier" = proto.Field( @@ -148,17 +177,30 @@ class ShareablePreviewOrError(proto.Message): oneof="generate_shareable_preview_response", message=status_pb2.Status, ) + ad_group_ad: str = proto.Field( + proto.STRING, + number=4, + oneof="identifier", + ) class ShareablePreviewResult(proto.Message): r"""Message to hold a shareable preview result. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: shareable_preview_url (str): - The shareable preview URL. + The shareable preview URL. Only populated if preview type is + UI_PREVIEW or unset. expiration_date_time (str): Expiration date time using the ISO-8601 format. + youtube_live_preview_result (google.ads.googleads.v23.services.types.YouTubeLivePreviewResult): + The result of a YouTube live preview. Only populated for + preview type YOUTUBE_LIVE_PREVIEW. + + This field is a member of `oneof`_ ``result``. """ shareable_preview_url: str = proto.Field( @@ -169,6 +211,32 @@ class ShareablePreviewResult(proto.Message): proto.STRING, number=2, ) + youtube_live_preview_result: "YouTubeLivePreviewResult" = proto.Field( + proto.MESSAGE, + number=3, + oneof="result", + message="YouTubeLivePreviewResult", + ) + + +class YouTubeLivePreviewResult(proto.Message): + r"""Message to hold a YouTube live preview result. + + Attributes: + youtube_preview_url (str): + The shareable preview URL for YouTube videos. + youtube_tv_preview_url (str): + The shareable preview URL for YouTube TV. + """ + + youtube_preview_url: str = proto.Field( + proto.STRING, + number=1, + ) + youtube_tv_preview_url: str = proto.Field( + proto.STRING, + number=2, + ) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/pyproject.toml b/pyproject.toml index 21d1ee3a4..f46fc7049 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ build-backend = "setuptools.build_meta" [project] name = "google-ads" -version = "29.2.0" +version = "30.0.0" description = "Client library for the Google Ads API" readme = "./README.rst" requires-python = ">=3.9, <3.15"