Skip to content

Commit df5094d

Browse files
authored
Added annotations to google/ads/googleads/*.py files (#957)
1 parent a032270 commit df5094d

File tree

5 files changed

+252
-167
lines changed

5 files changed

+252
-167
lines changed

google/ads/googleads/client.py

Lines changed: 99 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,22 @@
1717
import logging.config
1818

1919
from google.api_core.gapic_v1.client_info import ClientInfo
20-
import grpc.experimental
20+
import grpc
2121
from proto.enums import ProtoEnumMeta
2222

23+
from google.protobuf.message import Message as ProtobufMessageType
24+
from proto import Message as ProtoPlusMessageType
25+
2326
from google.ads.googleads import config, oauth2, util
2427
from 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

Comments
 (0)