Skip to content

Commit 550817d

Browse files
feat: Add type hints and annotations to audience_insights example
This commit introduces type hints for function arguments, return values, and local variables in `examples/audience_insights/generate_audience_insights.py`. Key changes include: - Added type hints to all function signatures and return types. - Added inline type hints for variables within functions. - Imported necessary types from `typing`, Google Ads client libraries, services, enums, and types modules. - Ensured proper organization and removal of unused or duplicate imports. - Updated some variable assignments to use specific Enum members for clarity (e.g., `AudienceInsightsDimensionEnum`). - Replaced some string formatting with f-strings in exception handling. These changes improve code readability, maintainability, and help with static analysis, making your example code more robust and easier to understand.
1 parent 4f350a8 commit 550817d

File tree

1 file changed

+115
-58
lines changed

1 file changed

+115
-58
lines changed

examples/audience_insights/generate_audience_insights.py

Lines changed: 115 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,54 @@
1414
# limitations under the License.
1515
"""This example illustrates how to generate audience insights."""
1616

17-
import argparse
1817
import argparse
1918
import sys
19+
from typing import Any
2020

2121
from google.ads.googleads.client import GoogleAdsClient
2222
from google.ads.googleads.errors import GoogleAdsException
23+
from google.ads.googleads.v19.enums.types import (
24+
AudienceInsightsDimensionEnum,
25+
)
26+
from google.ads.googleads.v19.services.services.audience_insights_service import (
27+
AudienceInsightsServiceClient,
28+
)
29+
from google.ads.googleads.v19.services.services.google_ads_service import (
30+
GoogleAdsServiceClient,
31+
)
32+
from google.ads.googleads.v19.types.audience_insights_service import (
33+
AudienceInsightsAttribute,
34+
GenerateAudienceCompositionInsightsRequest,
35+
GenerateAudienceCompositionInsightsResponse,
36+
GenerateSuggestedTargetingInsightsRequest,
37+
GenerateSuggestedTargetingInsightsResponse,
38+
InsightsAudienceAttributeGroup,
39+
ListAudienceInsightsAttributesRequest,
40+
ListAudienceInsightsAttributesResponse,
41+
)
42+
from google.ads.googleads.v19.types.common import LocationInfo
2343

2444

25-
def main(client, customer_id, custom_name):
45+
def main(
46+
client: GoogleAdsClient, customer_id: str, custom_name: str
47+
) -> None:
2648
"""The main method that creates all necessary entities for the example.
2749
2850
Args:
2951
client: an initialized GoogleAdsClient instance.
3052
customer_id: a client customer ID.
3153
custom_name: custom name to define audience.
3254
"""
33-
location_id = "2840" # US
34-
product_name = "Google"
35-
user_interest_category = "92948" # Technology
55+
location_id: str = "2840" # US
56+
product_name: str = "Google"
57+
user_interest_category: str = "92948" # Technology
3658
# Initialize appropriate services.
37-
audience_insights_service = client.get_service("AudienceInsightsService")
38-
googleads_service = client.get_service("GoogleAdsService")
59+
audience_insights_service: AudienceInsightsServiceClient = client.get_service(
60+
"AudienceInsightsService"
61+
)
62+
googleads_service: GoogleAdsServiceClient = client.get_service(
63+
"GoogleAdsService"
64+
)
3965

4066
audience_composition_insights(
4167
client,
@@ -44,35 +70,35 @@ def main(client, customer_id, custom_name):
4470
customer_id,
4571
location_id,
4672
user_interest_category,
47-
custom_name
73+
custom_name,
4874
)
4975
generate_suggested_targeting_insights(
5076
client,
5177
audience_insights_service,
5278
googleads_service,
5379
customer_id,
5480
location_id,
55-
custom_name
81+
custom_name,
5682
)
5783
list_audience_insights_attributes(
5884
client,
5985
audience_insights_service,
6086
customer_id,
6187
product_name,
62-
custom_name
88+
custom_name,
6389
)
6490

6591

6692
# [START composition_insights]
6793
def audience_composition_insights(
68-
client,
69-
audience_insights_service,
70-
googleads_service,
71-
customer_id,
72-
location_id,
73-
user_interest,
74-
custom_name
75-
):
94+
client: GoogleAdsClient,
95+
audience_insights_service: AudienceInsightsServiceClient,
96+
googleads_service: GoogleAdsServiceClient,
97+
customer_id: str,
98+
location_id: str,
99+
user_interest: str,
100+
custom_name: str,
101+
) -> None:
76102
"""Returns a collection of attributes represented in an audience of interest.
77103
78104
Please refere here for more:
@@ -88,46 +114,54 @@ def audience_composition_insights(
88114
user_interest: The criterion ID of the category.
89115
custom_name: custom defined name.
90116
"""
91-
request = client.get_type("GenerateAudienceCompositionInsightsRequest")
117+
request: GenerateAudienceCompositionInsightsRequest = client.get_type(
118+
"GenerateAudienceCompositionInsightsRequest"
119+
)
92120
request.customer_id = customer_id
93121

94-
insights_info = client.get_type("InsightsAudienceAttributeGroup")
95-
attributes = client.get_type("AudienceInsightsAttribute")
96-
attributes.user_interest.user_interest_category = googleads_service.user_interest_path(
97-
customer_id, user_interest
122+
insights_info: InsightsAudienceAttributeGroup = client.get_type(
123+
"InsightsAudienceAttributeGroup"
124+
)
125+
attributes: AudienceInsightsAttribute = client.get_type(
126+
"AudienceInsightsAttribute"
127+
)
128+
attributes.user_interest.user_interest_category = (
129+
googleads_service.user_interest_path(customer_id, user_interest)
98130
)
99131

100132
insights_info.attributes.append(attributes)
101133
request.audience.topic_audience_combinations.append(insights_info)
102134

103-
location_info = client.get_type("LocationInfo")
135+
location_info: LocationInfo = client.get_type("LocationInfo")
104136
location_info.geo_target_constant = (
105137
googleads_service.geo_target_constant_path(location_id)
106138
)
107139
request.audience.country_locations.append(location_info)
108140

109141
request.customer_insights_group = custom_name
110-
request.dimensions = (
111-
"AFFINITY_USER_INTEREST",
112-
"IN_MARKET_USER_INTEREST",
113-
"YOUTUBE_CHANNEL",
114-
)
115-
response = audience_insights_service.generate_audience_composition_insights(
116-
request=request
142+
request.dimensions = [
143+
client.enums.AudienceInsightsDimensionEnum.AFFINITY_USER_INTEREST,
144+
client.enums.AudienceInsightsDimensionEnum.IN_MARKET_USER_INTEREST,
145+
client.enums.AudienceInsightsDimensionEnum.YOUTUBE_CHANNEL,
146+
]
147+
response: GenerateAudienceCompositionInsightsResponse = (
148+
audience_insights_service.generate_audience_composition_insights(
149+
request=request
150+
)
117151
)
118152
print(response)
119153
# [END composition_insights]
120154

121155

122156
# [START targeted_insights]
123157
def generate_suggested_targeting_insights(
124-
client,
125-
audience_insights_service,
126-
googleads_service,
127-
customer_id,
128-
location_id,
129-
custom_name
130-
):
158+
client: GoogleAdsClient,
159+
audience_insights_service: AudienceInsightsServiceClient,
160+
googleads_service: GoogleAdsServiceClient,
161+
customer_id: str,
162+
location_id: str,
163+
custom_name: str,
164+
) -> None:
131165
"""Returns a collection of targeting insights (e.g.targetable audiences)
132166
that are relevant to the requested audience.
133167
@@ -140,30 +174,38 @@ def generate_suggested_targeting_insights(
140174
location_id: The location ID for the audience of interest.
141175
custom_name: custom defined name.
142176
"""
143-
request = client.get_type("GenerateSuggestedTargetingInsightsRequest")
177+
request: GenerateSuggestedTargetingInsightsRequest = client.get_type(
178+
"GenerateSuggestedTargetingInsightsRequest"
179+
)
144180

145181
request.customer_id = customer_id
146182
request.customer_insights_group = custom_name
147183

148-
audience_definition = request.audience_definition
149-
location_info = client.get_type("LocationInfo")
184+
audience_definition: Any = request.audience_definition
185+
location_info: LocationInfo = client.get_type("LocationInfo")
150186
location_info.geo_target_constant = (
151187
googleads_service.geo_target_constant_path(location_id)
152188
)
153189
audience_definition.audience.country_locations.append(location_info)
154190

155191
request.audience_definition = audience_definition
156-
response = audience_insights_service.generate_suggested_targeting_insights(
157-
request=request
192+
response: GenerateSuggestedTargetingInsightsResponse = (
193+
audience_insights_service.generate_suggested_targeting_insights(
194+
request=request
195+
)
158196
)
159197
print(response)
160198
# [END targeted_insights]
161199

162200

163201
# [START insights_attributes]
164202
def list_audience_insights_attributes(
165-
client, audience_insights_service, customer_id, product_name, custom_name
166-
):
203+
client: GoogleAdsClient,
204+
audience_insights_service: AudienceInsightsServiceClient,
205+
customer_id: str,
206+
product_name: str,
207+
custom_name: str,
208+
) -> None:
167209
"""Searches for audience attributes that can be used to generate insights.
168210
169211
Args:
@@ -174,25 +216,38 @@ def list_audience_insights_attributes(
174216
product_name: The brand/product for which insights are expected.
175217
custom_name: custom defined name.
176218
"""
177-
request = client.get_type("ListAudienceInsightsAttributesRequest")
219+
request: ListAudienceInsightsAttributesRequest = client.get_type(
220+
"ListAudienceInsightsAttributesRequest"
221+
)
178222

179223
request.customer_id = customer_id
180224
request.query_text = product_name
181-
category_dimension = client.enums.AudienceInsightsDimensionEnum.CATEGORY
182-
kg_dimension = client.enums.AudienceInsightsDimensionEnum.KNOWLEDGE_GRAPH
225+
category_dimension: AudienceInsightsDimensionEnum.AudienceInsightsDimension = (
226+
client.enums.AudienceInsightsDimensionEnum.CATEGORY
227+
)
228+
kg_dimension: AudienceInsightsDimensionEnum.AudienceInsightsDimension = (
229+
client.enums.AudienceInsightsDimensionEnum.KNOWLEDGE_GRAPH
230+
)
183231
request.dimensions = [category_dimension, kg_dimension]
184232
request.customer_insights_group = custom_name
185-
response = audience_insights_service.list_audience_insights_attributes(
186-
request=request
233+
response: ListAudienceInsightsAttributesResponse = (
234+
audience_insights_service.list_audience_insights_attributes(
235+
request=request
236+
)
187237
)
188238
for attribute in response.attributes:
189-
if attribute.dimension == 3:
239+
if (
240+
attribute.dimension
241+
== client.enums.AudienceInsightsDimensionEnum.KNOWLEDGE_GRAPH
242+
):
190243
print(attribute.attribute.entity.knowledge_graph_machine_id)
191244
# [END insights_attributes]
192245

193246

194247
if __name__ == "__main__":
195-
parser = argparse.ArgumentParser(description="Create audience insights.")
248+
parser: argparse.ArgumentParser = argparse.ArgumentParser(
249+
description="Create audience insights."
250+
)
196251

197252
# The following argument(s) should be provided to run the example.
198253
parser.add_argument(
@@ -211,24 +266,26 @@ def list_audience_insights_attributes(
211266
help="Custom name to indentify audiences",
212267
)
213268
parser.add_argument
214-
args = parser.parse_args()
269+
args: argparse.Namespace = parser.parse_args()
215270

216271
# GoogleAdsClient will read the google-ads.yaml configuration file in the
217272
# home directory if none is specified.
218-
googleads_client = GoogleAdsClient.load_from_storage(version="v19")
273+
googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage(
274+
version="v19"
275+
)
219276

220277
try:
221278
main(googleads_client, args.customer_id, args.custom_name)
222279
except GoogleAdsException as ex:
223280
print(
224-
'Request with ID "{}" failed with status "%s" and includes the '
225-
"following errors:".format(ex.request_id, ex.error.code().name)
281+
f'Request with ID "{ex.request_id}" failed with status '
282+
f'"{ex.error.code().name}" and includes the following errors:'
226283
)
227284
for error in ex.failure.errors:
228-
print('\tError with message "{}".'.format(error.message))
285+
print(f'\tError with message "{error.message}".')
229286
if error.location:
230287
for field_path_element in error.location.field_path_elements:
231288
print(
232-
"\t\tOn field: {}".format(field_path_element.field_name)
289+
f"\t\tOn field: {field_path_element.field_name}"
233290
)
234291
sys.exit(1)

0 commit comments

Comments
 (0)