2323from itertools import product
2424import multiprocessing
2525import time
26+ from typing import Any , Dict , Iterable , List , Tuple , Union
2627
2728from google .ads .googleads .client import GoogleAdsClient
2829from google .ads .googleads .errors import GoogleAdsException
3536MAX_RETRIES = 5
3637
3738
38- def main (client , customer_ids ):
39+ def main (
40+ client : GoogleAdsClient , customer_ids : List [str ]
41+ ) -> None :
3942 """The main method that creates all necessary entities for the example.
4043
4144 Args:
@@ -53,17 +56,19 @@ def main(client, customer_ids):
5356 FROM ad_group
5457 WHERE segments.date DURING LAST_30_DAYS"""
5558
56- inputs = generate_inputs (
59+ inputs : Iterable [ Tuple [ GoogleAdsClient , str , str ]] = generate_inputs (
5760 client , customer_ids , [campaign_query , ad_group_query ]
5861 )
5962 with multiprocessing .Pool (MAX_PROCESSES ) as pool :
6063 # Call issue_search_request on each input, parallelizing the work
6164 # across processes in the pool.
62- results = pool .starmap (issue_search_request , inputs )
65+ results : List [Tuple [bool , Dict [str , Any ]]] = pool .starmap (
66+ issue_search_request , inputs
67+ )
6368
6469 # Partition our results into successful and failed results.
65- successes = []
66- failures = []
70+ successes : List [ Dict [ str , Any ]] = []
71+ failures : List [ Dict [ str , Any ]] = []
6772 for res in results :
6873 if res [0 ]:
6974 successes .append (res [1 ])
@@ -101,7 +106,9 @@ def main(client, customer_ids):
101106 print (f"\t \t On field: { field_path_element .field_name } " )
102107
103108
104- def issue_search_request (client , customer_id , query ):
109+ def issue_search_request (
110+ client : GoogleAdsClient , customer_id : str , query : str
111+ ) -> Tuple [bool , Dict [str , Any ]]:
105112 """Issues a search request using streaming.
106113
107114 Retries if a GoogleAdsException is caught, until MAX_RETRIES is reached.
@@ -111,27 +118,27 @@ def issue_search_request(client, customer_id, query):
111118 customer_id: a client customer ID str.
112119 query: a GAQL query str.
113120 """
114- ga_service = client .get_service ("GoogleAdsService" )
115- retry_count = 0
121+ ga_service : Any = client .get_service ("GoogleAdsService" )
122+ retry_count : int = 0
116123 # Retry until we've reached MAX_RETRIES or have successfully received a
117124 # response.
118125 while True :
119126 try :
120- stream = ga_service .search_stream (
127+ stream : Any = ga_service .search_stream (
121128 customer_id = customer_id , query = query
122129 )
123130 # Returning a list of GoogleAdsRows will result in a
124131 # PicklingError, so instead we put the GoogleAdsRow data
125132 # into a list of str results and return that.
126- result_strings = []
133+ result_strings : List [ str ] = []
127134 for batch in stream :
128135 for row in batch .results :
129- ad_group_id = (
136+ ad_group_id : str = (
130137 f"Ad Group ID { row .ad_group .id } in "
131138 if "ad_group.id" in query
132139 else ""
133140 )
134- result_string = (
141+ result_string : str = (
135142 f"{ ad_group_id } "
136143 f"Campaign ID { row .campaign .id } "
137144 f"had { row .metrics .impressions } impressions "
@@ -157,7 +164,11 @@ def issue_search_request(client, customer_id, query):
157164 )
158165
159166
160- def generate_inputs (client , customer_ids , queries ):
167+ def generate_inputs (
168+ client : GoogleAdsClient ,
169+ customer_ids : List [str ],
170+ queries : List [str ],
171+ ) -> Iterable [Tuple [GoogleAdsClient , str , str ]]:
161172 """Generates all inputs to feed into search requests.
162173
163174 A GoogleAdsService instance cannot be serialized with pickle for parallel
@@ -173,7 +184,7 @@ def generate_inputs(client, customer_ids, queries):
173184
174185
175186if __name__ == "__main__" :
176- parser = argparse .ArgumentParser (
187+ parser : argparse . ArgumentParser = argparse .ArgumentParser (
177188 description = "Download a set of reports in parallel from a list of "
178189 "accounts."
179190 )
@@ -192,11 +203,13 @@ def generate_inputs(client, customer_ids, queries):
192203 type = str ,
193204 help = "The login customer ID (optional)." ,
194205 )
195- args = parser .parse_args ()
206+ args : argparse . Namespace = parser .parse_args ()
196207
197208 # GoogleAdsClient will read the google-ads.yaml configuration file in the
198209 # home directory if none is specified.
199- googleads_client = GoogleAdsClient .load_from_storage (version = "v19" )
210+ googleads_client : GoogleAdsClient = GoogleAdsClient .load_from_storage (
211+ version = "v19"
212+ )
200213 # Override the login_customer_id on the GoogleAdsClient, if specified.
201214 if args .login_customer_id is not None :
202215 googleads_client .login_customer_id = args .login_customer_id
0 commit comments