1717import logging .config
1818
1919from google .api_core .gapic_v1 .client_info import ClientInfo
20- import grpc . experimental
20+ import grpc
2121from proto .enums import ProtoEnumMeta
2222
23+ from google .protobuf .message import Message as ProtobufMessageType
24+ from proto import Message as ProtoPlusMessageType
25+
2326from google .ads .googleads import config , oauth2 , util
2427from google .ads .googleads .interceptors import (
2528 MetadataInterceptor ,
2629 ExceptionInterceptor ,
2730 LoggingInterceptor ,
2831)
2932
33+ from types import ModuleType
34+ from typing import Any , Dict , List , Tuple , Union
35+
3036_logger = logging .getLogger (__name__ )
3137
3238_SERVICE_CLIENT_TEMPLATE = "{}Client"
@@ -60,19 +66,18 @@ class _EnumGetter:
6066 class instances when accessed.
6167 """
6268
63- def __init__ (self , client ) :
69+ def __init__ (self , client : "GoogleAdsClient" ) -> None :
6470 """Initializer for the _EnumGetter class.
6571
6672 Args:
67- version: a str indicating the version of the Google Ads API to be
68- used.
73+ client: An instance of the GoogleAdsClient class.
6974 """
70- self ._client = client
71- self ._version = client .version or _DEFAULT_VERSION
72- self ._enums = None
73- self ._use_proto_plus = client .use_proto_plus
75+ self ._client : "GoogleAdsClient" = client
76+ self ._version : str = client .version or _DEFAULT_VERSION
77+ self ._enums : Union [ Tuple [ str ], None ] = None
78+ self ._use_proto_plus : bool = client .use_proto_plus
7479
75- def __dir__ (self ):
80+ def __dir__ (self ) -> Tuple [ str ] :
7681 """Overrides behavior when dir() is called on instances of this class.
7782
7883 It's useful to use dir() to see a list of available attributes. Since
@@ -86,7 +91,7 @@ def __dir__(self):
8691
8792 return self ._enums
8893
89- def __getattr__ (self , name ) :
94+ def __getattr__ (self , name : str ) -> Union [ ProtoPlusMessageType , ProtobufMessageType ] :
9095 """Dynamically loads the given enum class instance.
9196
9297 Args:
@@ -95,14 +100,14 @@ def __getattr__(self, name):
95100 Returns:
96101 An instance of the enum proto message class.
97102 """
98- if not name in self .__dir__ ():
103+ if name not in self .__dir__ ():
99104 raise AttributeError (
100105 f"'{ type (self ).__name__ } ' object has no attribute '{ name } '"
101106 )
102107 try :
103108 enum_class = self ._client .get_type (name )
104109
105- if self ._use_proto_plus == True :
110+ if self ._use_proto_plus :
106111 for attr in dir (enum_class ):
107112 attr_val = getattr (enum_class , attr )
108113 if isinstance (attr_val , ProtoEnumMeta ):
@@ -114,7 +119,7 @@ def __getattr__(self, name):
114119 f"'{ type (self ).__name__ } ' object has no attribute '{ name } '"
115120 )
116121
117- def __getstate__ (self ):
122+ def __getstate__ (self ) -> Dict [ str , Any ] :
118123 """Returns self serialized as a dict.
119124
120125 Since this class overrides __getattr__ we define this method to help
@@ -126,7 +131,7 @@ def __getstate__(self):
126131 """
127132 return self .__dict__ .copy ()
128133
129- def __setstate__ (self , d ) :
134+ def __setstate__ (self , d : Dict [ str , Any ]) -> None :
130135 """Deserializes self with the given dictionary.
131136
132137 Since this class overrides __getattr__ we define this method to help
@@ -143,7 +148,11 @@ class GoogleAdsClient:
143148 """Google Ads client used to configure settings and fetch services."""
144149
145150 @classmethod
146- def copy_from (cls , destination , origin ):
151+ def copy_from (
152+ cls ,
153+ destination : Union [ProtoPlusMessageType , ProtobufMessageType ],
154+ origin : Union [ProtoPlusMessageType , ProtobufMessageType ]
155+ ) -> Union [ProtoPlusMessageType , ProtobufMessageType ]:
147156 """Copies protobuf and proto-plus messages into one-another.
148157
149158 This method consolidates the CopyFrom logic of protobuf and proto-plus
@@ -157,7 +166,7 @@ def copy_from(cls, destination, origin):
157166 return util .proto_copy_from (destination , origin )
158167
159168 @classmethod
160- def _get_client_kwargs (cls , config_data ) :
169+ def _get_client_kwargs (cls , config_data : Dict [ str , Any ]) -> Dict [ str , Any ] :
161170 """Converts configuration dict into kwargs required by the client.
162171
163172 Args:
@@ -185,7 +194,7 @@ def _get_client_kwargs(cls, config_data):
185194 }
186195
187196 @classmethod
188- def _get_api_services_by_version (cls , version ) :
197+ def _get_api_services_by_version (cls , version : str ) -> ModuleType :
189198 """Returns a module with all services and types for a given API version.
190199
191200 Args:
@@ -207,7 +216,9 @@ def _get_api_services_by_version(cls, version):
207216 return version_module
208217
209218 @classmethod
210- def load_from_env (cls , version = None ):
219+ def load_from_env (
220+ cls , version : Union [str , None ] = None
221+ ) -> "GoogleAdsClient" :
211222 """Creates a GoogleAdsClient with data stored in the env variables.
212223
213224 Args:
@@ -220,12 +231,14 @@ def load_from_env(cls, version=None):
220231 Raises:
221232 ValueError: If the configuration lacks a required field.
222233 """
223- config_data = config .load_from_env ()
224- kwargs = cls ._get_client_kwargs (config_data )
234+ config_data : Dict [ str , Any ] = config .load_from_env ()
235+ kwargs : Dict [ str , Any ] = cls ._get_client_kwargs (config_data )
225236 return cls (** dict (version = version , ** kwargs ))
226237
227238 @classmethod
228- def load_from_string (cls , yaml_str , version = None ):
239+ def load_from_string (
240+ cls , yaml_str : str , version : Union [str , None ] = None
241+ ) -> "GoogleAdsClient" :
229242 """Creates a GoogleAdsClient with data stored in the YAML string.
230243
231244 Args:
@@ -240,12 +253,14 @@ def load_from_string(cls, yaml_str, version=None):
240253 Raises:
241254 ValueError: If the configuration lacks a required field.
242255 """
243- config_data = config .parse_yaml_document_to_dict (yaml_str )
244- kwargs = cls ._get_client_kwargs (config_data )
256+ config_data : Dict [ str , Any ] = config .parse_yaml_document_to_dict (yaml_str )
257+ kwargs : Dict [ str , Any ] = cls ._get_client_kwargs (config_data )
245258 return cls (** dict (version = version , ** kwargs ))
246259
247260 @classmethod
248- def load_from_dict (cls , config_dict , version = None ):
261+ def load_from_dict (
262+ cls , config_dict : Dict [str , Any ], version : Union [str , None ] = None
263+ ) -> "GoogleAdsClient" :
249264 """Creates a GoogleAdsClient with data stored in the config_dict.
250265
251266 Args:
@@ -260,12 +275,14 @@ def load_from_dict(cls, config_dict, version=None):
260275 Raises:
261276 ValueError: If the configuration lacks a required field.
262277 """
263- config_data = config .load_from_dict (config_dict )
264- kwargs = cls ._get_client_kwargs (config_data )
278+ config_data : Dict [ str , Any ] = config .load_from_dict (config_dict )
279+ kwargs : Dict [ str , Any ] = cls ._get_client_kwargs (config_data )
265280 return cls (** dict (version = version , ** kwargs ))
266281
267282 @classmethod
268- def load_from_storage (cls , path = None , version = None ):
283+ def load_from_storage (
284+ cls , path : Union [str , None ] = None , version : Union [str , None ] = None
285+ ) -> "GoogleAdsClient" :
269286 """Creates a GoogleAdsClient with data stored in the specified file.
270287
271288 Args:
@@ -282,22 +299,22 @@ def load_from_storage(cls, path=None, version=None):
282299 IOError: If the configuration file can't be loaded.
283300 ValueError: If the configuration file lacks a required field.
284301 """
285- config_data = config .load_from_yaml_file (path )
286- kwargs = cls ._get_client_kwargs (config_data )
302+ config_data : Dict [ str , Any ] = config .load_from_yaml_file (path )
303+ kwargs : Dict [ str , Any ] = cls ._get_client_kwargs (config_data )
287304 return cls (** dict (version = version , ** kwargs ))
288305
289306 def __init__ (
290307 self ,
291- credentials ,
292- developer_token ,
293- endpoint = None ,
294- login_customer_id = None ,
295- logging_config = None ,
296- linked_customer_id = None ,
297- version = None ,
298- http_proxy = None ,
299- use_proto_plus = False ,
300- use_cloud_org_for_api_access = None ,
308+ credentials : Dict [ str , Any ] ,
309+ developer_token : str ,
310+ endpoint : Union [ str , None ] = None ,
311+ login_customer_id : Union [ str , None ] = None ,
312+ logging_config : Union [ Dict [ str , Any ], None ] = None ,
313+ linked_customer_id : Union [ str , None ] = None ,
314+ version : Union [ str , None ] = None ,
315+ http_proxy : Union [ str , None ] = None ,
316+ use_proto_plus : bool = False ,
317+ use_cloud_org_for_api_access : Union [ str , None ] = None ,
301318 ):
302319 """Initializer for the GoogleAdsClient.
303320
@@ -321,22 +338,29 @@ def __init__(
321338 if logging_config :
322339 logging .config .dictConfig (logging_config )
323340
324- self .credentials = credentials
325- self .developer_token = developer_token
326- self .endpoint = endpoint
327- self .login_customer_id = login_customer_id
328- self .linked_customer_id = linked_customer_id
329- self .version = version
330- self .http_proxy = http_proxy
331- self .use_proto_plus = use_proto_plus
332- self .use_cloud_org_for_api_access = use_cloud_org_for_api_access
333- self .enums = _EnumGetter (self )
341+ self .credentials : Dict [str , Any ] = credentials
342+ self .developer_token : str = developer_token
343+ self .endpoint : Union [str , None ] = endpoint
344+ self .login_customer_id : Union [str , None ] = login_customer_id
345+ self .linked_customer_id : Union [str , None ] = linked_customer_id
346+ self .version : Union [str , None ] = version
347+ self .http_proxy : Union [str , None ] = http_proxy
348+ self .use_proto_plus : bool = use_proto_plus
349+ self .use_cloud_org_for_api_access : Union [str , None ] = (
350+ use_cloud_org_for_api_access
351+ )
352+ self .enums : _EnumGetter = _EnumGetter (self )
334353
335354 # If given, write the http_proxy channel option for GRPC to use
336355 if http_proxy :
337356 _GRPC_CHANNEL_OPTIONS .append (("grpc.http_proxy" , http_proxy ))
338357
339- def get_service (self , name , version = _DEFAULT_VERSION , interceptors = None ):
358+ def get_service (
359+ self ,
360+ name : str ,
361+ version : str = _DEFAULT_VERSION ,
362+ interceptors : Union [list , None ] = None ,
363+ ) -> Any :
340364 """Returns a service client instance for the specified service_name.
341365
342366 Args:
@@ -359,13 +383,15 @@ def get_service(self, name, version=_DEFAULT_VERSION, interceptors=None):
359383 # override any version specified as an argument.
360384 version = self .version if self .version else version
361385 # api_module = self._get_api_services_by_version(version)
362- services_path = f"google.ads.googleads.{ version } .services.services"
363- snaked = util .convert_upper_case_to_snake_case (name )
386+ services_path : str = (
387+ f"google.ads.googleads.{ version } .services.services"
388+ )
389+ snaked : str = util .convert_upper_case_to_snake_case (name )
364390 interceptors = interceptors or []
365391
366392 try :
367- service_module = import_module (f"{ services_path } .{ snaked } " )
368- service_client_class = util .get_nested_attr (
393+ service_module : Any = import_module (f"{ services_path } .{ snaked } " )
394+ service_client_class : Any = util .get_nested_attr (
369395 service_module , _SERVICE_CLIENT_TEMPLATE .format (name )
370396 )
371397 except (AttributeError , ModuleNotFoundError ):
@@ -374,40 +400,42 @@ def get_service(self, name, version=_DEFAULT_VERSION, interceptors=None):
374400 "Ads API {}." .format (name , version )
375401 )
376402
377- service_transport_class = service_client_class .get_transport_class ()
403+ service_transport_class : Any = service_client_class .get_transport_class ()
378404
379- endpoint = (
405+ endpoint : str = (
380406 self .endpoint
381407 if self .endpoint
382408 else service_client_class .DEFAULT_ENDPOINT
383409 )
384410
385- channel = service_transport_class .create_channel (
411+ channel : grpc . Channel = service_transport_class .create_channel (
386412 host = endpoint ,
387413 credentials = self .credentials ,
388414 options = _GRPC_CHANNEL_OPTIONS ,
389415 )
390416
391- interceptors = interceptors + [
417+ interceptors : List [ Union [ grpc . UnaryUnaryClientInterceptor , grpc . UnaryStreamClientInterceptor ]] = interceptors + [
392418 MetadataInterceptor (
393419 self .developer_token ,
394420 self .login_customer_id ,
395421 self .linked_customer_id ,
396422 self .use_cloud_org_for_api_access ,
397423 ),
398424 LoggingInterceptor (_logger , version , endpoint ),
399- ExceptionInterceptor (version , use_proto_plus = self .use_proto_plus ),
425+ ExceptionInterceptor (
426+ version , use_proto_plus = self .use_proto_plus
427+ ),
400428 ]
401429
402- channel = grpc .intercept_channel (channel , * interceptors )
430+ channel : grpc . Channel = grpc .intercept_channel (channel , * interceptors )
403431
404- service_transport = service_transport_class (
432+ service_transport : Any = service_transport_class (
405433 channel = channel , client_info = _CLIENT_INFO
406434 )
407435
408436 return service_client_class (transport = service_transport )
409437
410- def get_type (self , name , version = _DEFAULT_VERSION ):
438+ def get_type (self , name : str , version : str = _DEFAULT_VERSION ) -> Union [ ProtoPlusMessageType , ProtobufMessageType ] :
411439 """Returns the specified common, enum, error, or resource type.
412440
413441 Args:
@@ -441,22 +469,22 @@ def get_type(self, name, version=_DEFAULT_VERSION):
441469
442470 # If version is specified when the instance is created,
443471 # override any version specified as an argument.
444- version = self .version if self .version else version
445- type_classes = self ._get_api_services_by_version (version )
472+ version : str = self .version if self .version else version
473+ type_classes : ModuleType = self ._get_api_services_by_version (version )
446474
447- for type in _MESSAGE_TYPES :
448- if type == "services" :
449- path = f"{ type } .types.{ name } "
475+ for type_name in _MESSAGE_TYPES :
476+ if type_name == "services" :
477+ path : str = f"{ type_name } .types.{ name } "
450478 else :
451- path = f"{ type } .{ name } "
479+ path : str = f"{ type_name } .{ name } "
452480
453481 try :
454- message_class = util .get_nested_attr (type_classes , path )
482+ message_class : Union [ ProtoPlusMessageType , ProtobufMessageType ] = util .get_nested_attr (type_classes , path ) # type: ignore[no-untyped-call]
455483
456- if self .use_proto_plus == True :
484+ if self .use_proto_plus :
457485 return message_class ()
458486 else :
459- return util .convert_proto_plus_to_protobuf (message_class ())
487+ return util .convert_proto_plus_to_protobuf (message_class ()) # type: ignore[no-untyped-call]
460488 except AttributeError :
461489 pass
462490
0 commit comments