diff --git a/google/ads/googleads/client.py b/google/ads/googleads/client.py index 0f150fd7d..64ef72b44 100644 --- a/google/ads/googleads/client.py +++ b/google/ads/googleads/client.py @@ -104,7 +104,9 @@ def __dir__(self) -> Tuple[str]: return self._enums - def __getattr__(self, name: str) -> Union[ProtoPlusMessageType, ProtobufMessageType]: + def __getattr__( + self, name: str + ) -> Union[ProtoPlusMessageType, ProtobufMessageType]: """Dynamically loads the given enum class instance. Args: @@ -162,10 +164,10 @@ class GoogleAdsClient: @classmethod def copy_from( - cls, - destination: Union[ProtoPlusMessageType, ProtobufMessageType], - origin: Union[ProtoPlusMessageType, ProtobufMessageType] - ) -> Union[ProtoPlusMessageType, ProtobufMessageType]: + cls, + destination: Union[ProtoPlusMessageType, ProtobufMessageType], + origin: Union[ProtoPlusMessageType, ProtobufMessageType], + ) -> Union[ProtoPlusMessageType, ProtobufMessageType]: """Copies protobuf and proto-plus messages into one-another. This method consolidates the CopyFrom logic of protobuf and proto-plus @@ -204,7 +206,6 @@ def _get_client_kwargs(cls, config_data: Dict[str, Any]) -> Dict[str, Any]: "use_cloud_org_for_api_access": config_data.get( "use_cloud_org_for_api_access" ), - "gaada": config_data.get("gaada"), } @classmethod @@ -267,7 +268,9 @@ def load_from_string( Raises: ValueError: If the configuration lacks a required field. """ - config_data: Dict[str, Any] = config.parse_yaml_document_to_dict(yaml_str) + config_data: Dict[str, Any] = config.parse_yaml_document_to_dict( + yaml_str + ) kwargs: Dict[str, Any] = cls._get_client_kwargs(config_data) return cls(**dict(version=version, **kwargs)) @@ -329,7 +332,6 @@ def __init__( http_proxy: Union[str, None] = None, use_proto_plus: bool = False, use_cloud_org_for_api_access: Union[str, None] = None, - gaada: Union[str, None] = None, ): """Initializer for the GoogleAdsClient. @@ -349,7 +351,6 @@ def __init__( of developer token to determine your Google Ads API access levels. Use this flag only if you are enrolled into a limited pilot that supports this configuration. - gaada: a str specifying the Google Ads API Assistant version. """ if logging_config: logging.config.dictConfig(logging_config) @@ -366,7 +367,6 @@ def __init__( use_cloud_org_for_api_access ) self.enums: _EnumGetter = _EnumGetter(self) - self.gaada: Union[str, None] = gaada # If given, write the http_proxy channel option for GRPC to use if http_proxy: @@ -403,9 +403,7 @@ def get_service( # override any version specified as an argument. version = self.version if self.version else version # api_module = self._get_api_services_by_version(version) - services_path: str = ( - f"google.ads.googleads.{version}.services.services" - ) + services_path: str = f"google.ads.googleads.{version}.services.services" snaked: str = util.convert_upper_case_to_snake_case(name) interceptors = interceptors or [] @@ -446,14 +444,12 @@ def get_service( self.login_customer_id, self.linked_customer_id, self.use_cloud_org_for_api_access, - gaada=self.gaada, ), AsyncUnaryStreamMetadataInterceptor( self.developer_token, self.login_customer_id, self.linked_customer_id, self.use_cloud_org_for_api_access, - gaada=self.gaada, ), AsyncUnaryUnaryLoggingInterceptor(_logger, version, endpoint), AsyncUnaryStreamLoggingInterceptor(_logger, version, endpoint), @@ -485,7 +481,7 @@ def get_service( developer_token=self.developer_token, login_customer_id=self.login_customer_id, linked_customer_id=self.linked_customer_id, - use_cloud_org_for_api_access=self.use_cloud_org_for_api_access + use_cloud_org_for_api_access=self.use_cloud_org_for_api_access, ) return service_client_class(transport=service_transport) @@ -496,18 +492,20 @@ def get_service( options=_GRPC_CHANNEL_OPTIONS, ) - interceptors: List[Union[grpc.UnaryUnaryClientInterceptor, grpc.UnaryStreamClientInterceptor]] = interceptors + [ + interceptors: List[ + Union[ + grpc.UnaryUnaryClientInterceptor, + grpc.UnaryStreamClientInterceptor, + ] + ] = interceptors + [ MetadataInterceptor( self.developer_token, self.login_customer_id, self.linked_customer_id, self.use_cloud_org_for_api_access, - gaada=self.gaada, ), LoggingInterceptor(_logger, version, endpoint), - ExceptionInterceptor( - version, use_proto_plus=self.use_proto_plus - ), + ExceptionInterceptor(version, use_proto_plus=self.use_proto_plus), ] channel: grpc.Channel = grpc.intercept_channel(channel, *interceptors) @@ -525,12 +523,14 @@ def get_service( developer_token=self.developer_token, login_customer_id=self.login_customer_id, linked_customer_id=self.linked_customer_id, - use_cloud_org_for_api_access=self.use_cloud_org_for_api_access + use_cloud_org_for_api_access=self.use_cloud_org_for_api_access, ) return service_client_class(transport=service_transport) - def get_type(self, name: str, version: str = _DEFAULT_VERSION) -> Union[ProtoPlusMessageType, ProtobufMessageType]: + def get_type( + self, name: str, version: str = _DEFAULT_VERSION + ) -> Union[ProtoPlusMessageType, ProtobufMessageType]: """Returns the specified common, enum, error, or resource type. Args: diff --git a/google/ads/googleads/config.py b/google/ads/googleads/config.py index a8c96d53f..dfc7888fc 100644 --- a/google/ads/googleads/config.py +++ b/google/ads/googleads/config.py @@ -21,7 +21,6 @@ from typing import Any, Callable, List, Tuple, TypeVar, Union import yaml - _logger = logging.getLogger(__name__) @@ -35,7 +34,6 @@ "http_proxy", "use_cloud_org_for_api_access", "use_application_default_credentials", - "gaada", ) _CONFIG_FILE_PATH_KEY = ("configuration_file_path",) _OAUTH2_INSTALLED_APP_KEYS = ("client_id", "client_secret", "refresh_token") @@ -96,7 +94,9 @@ def parser_wrapper(*args: Any, **kwargs: Any) -> Any: parsed_config: dict[str, Any] = convert_login_customer_id_to_str( config_dict ) - parsed_config: dict[str, Any] = convert_linked_customer_id_to_str(parsed_config) + parsed_config: dict[str, Any] = convert_linked_customer_id_to_str( + parsed_config + ) config_keys: List[str] = parsed_config.keys() @@ -106,7 +106,9 @@ def parser_wrapper(*args: Any, **kwargs: Any) -> Any: # that needs to be returned by this method. if type(logging_config) is not dict: try: - parsed_config["logging"]: dict[str, Any] = json.loads(logging_config) + parsed_config["logging"]: dict[str, Any] = json.loads( + logging_config + ) # The logger is configured here in case deprecation warnings # need to be logged further down in this method. The logger # is otherwise configured by the GoogleAdsClient class. @@ -159,7 +161,9 @@ def parser_wrapper(*args: Any, **kwargs: Any) -> Any: # the string "False" is truthy and can easily be incorrectly # converted to the boolean True. value: Union[str, bool] = parsed_config.get("use_proto_plus", False) - parsed_config["use_proto_plus"]: bool = disambiguate_string_bool(value) + parsed_config["use_proto_plus"]: bool = disambiguate_string_bool( + value + ) if "use_application_default_credentials" in config_keys: # When loaded from YAML, YAML string or a dict, this value is @@ -168,8 +172,12 @@ def parser_wrapper(*args: Any, **kwargs: Any) -> Any: # variable we need to manually change it to the bool False because # the string "False" is truthy and can easily be incorrectly # converted to the boolean True. - value: Union[str, bool] = parsed_config.get("use_application_default_credentials", False) - parsed_config["use_application_default_credentials"]: bool = disambiguate_string_bool(value) + value: Union[str, bool] = parsed_config.get( + "use_application_default_credentials", False + ) + parsed_config["use_application_default_credentials"]: bool = ( + disambiguate_string_bool(value) + ) return parsed_config @@ -380,7 +388,7 @@ def get_oauth2_required_service_account_keys() -> tuple[str, ...]: def convert_login_customer_id_to_str( - config_data: dict[str, Any] + config_data: dict[str, Any], ) -> dict[str, Any]: """Parses a config dict's login_customer_id attr value to a str. @@ -403,7 +411,7 @@ def convert_login_customer_id_to_str( def convert_linked_customer_id_to_str( - config_data: dict[str, Any] + config_data: dict[str, Any], ) -> dict[str, Any]: """Parses a config dict's linked_customer_id attr value to a str. diff --git a/google/ads/googleads/interceptors/metadata_interceptor.py b/google/ads/googleads/interceptors/metadata_interceptor.py index 82f21ef5a..fe26e215f 100644 --- a/google/ads/googleads/interceptors/metadata_interceptor.py +++ b/google/ads/googleads/interceptors/metadata_interceptor.py @@ -24,14 +24,18 @@ # request user-agent directly by the google-api-core package: # https://github.com/googleapis/python-api-core/issues/416 from importlib import metadata +import os from typing import List, Optional, Tuple, Union from google.protobuf.internal import api_implementation from google.protobuf.message import Message as ProtobufMessageType import grpc -from google.ads.googleads.interceptors import Interceptor, MetadataType, ContinuationType - +from google.ads.googleads.interceptors import ( + Interceptor, + MetadataType, + ContinuationType, +) # Determine which version of the package is installed. try: @@ -47,20 +51,22 @@ else: _PB_IMPL_HEADER = "" +_GAADA = os.environ.get("GOOGLE_ADS_GAADA") + + class MetadataInterceptor( Interceptor, grpc.UnaryUnaryClientInterceptor, - grpc.UnaryStreamClientInterceptor + grpc.UnaryStreamClientInterceptor, ): """An interceptor that appends custom metadata to requests.""" def __init__( self, developer_token: str, - login_customer_id: Optional[str]= None, + login_customer_id: Optional[str] = None, linked_customer_id: Optional[str] = None, use_cloud_org_for_api_access: Optional[bool] = None, - gaada: Optional[str] = None, ): """Initialization method for this class. @@ -73,7 +79,6 @@ def __init__( of developer token to determine your Google Ads API access levels. Use this flag only if you are enrolled into a limited pilot that supports this configuration - gaada: a str specifying the Google Ads API Assistant version. """ self.developer_token_meta: Tuple[str, str] = ( "developer-token", @@ -89,13 +94,14 @@ def __init__( if linked_customer_id else None ) - self.gaada: Optional[str] = gaada - self.use_cloud_org_for_api_access: Optional[ - bool - ] = use_cloud_org_for_api_access + self.use_cloud_org_for_api_access: Optional[bool] = ( + use_cloud_org_for_api_access + ) def _update_client_call_details_metadata( - self, client_call_details: grpc.ClientCallDetails, metadata: MetadataType + self, + client_call_details: grpc.ClientCallDetails, + metadata: MetadataType, ): """Updates the client call details with additional metadata. @@ -107,12 +113,14 @@ def _update_client_call_details_metadata( An new instance of grpc.ClientCallDetails with additional metadata from the GoogleAdsClient. """ - client_call_details: grpc.ClientCallDetails = self.get_client_call_details_instance( - client_call_details.method, - client_call_details.timeout, - metadata, - client_call_details.credentials, - getattr(client_call_details, "wait_for_ready", None), + client_call_details: grpc.ClientCallDetails = ( + self.get_client_call_details_instance( + client_call_details.method, + client_call_details.timeout, + metadata, + client_call_details.credentials, + getattr(client_call_details, "wait_for_ready", None), + ) ) return client_call_details @@ -151,35 +159,12 @@ def _intercept( if self.linked_customer_id_meta: metadata.append(self.linked_customer_id_meta) - # TODO: This logic should be updated or removed once the following is - # fixed: https://github.com/googleapis/python-api-core/issues/416 - for i, metadatum_tuple in enumerate(metadata): - # Check if the user agent header key is in the current metadatum - if "x-goog-api-client" in metadatum_tuple: - metadatum: List[str] = list(metadatum_tuple) + metadata = self._append_metadata(metadata) - if self.gaada: - metadatum[1] += f" gaada/{self.gaada}" - - if _PROTOBUF_VERSION: - # Convert the tuple to a list so it can be modified. - # Check that "pb" isn't already included in the user agent. - if "pb" not in metadatum[1]: - # Append the protobuf version key value pair to the end of - # the string. - metadatum[1] += f" pb/{_PROTOBUF_VERSION}{_PB_IMPL_HEADER}" - # Convert the metadatum back to a tuple. - metadatum_tuple: Tuple[str, str] = tuple(metadatum) - - # Splice the metadatum back in its original position in - # order to preserve the order of the metadata list. - metadata[i] = metadatum_tuple - # Exit the loop since we already found the user agent. - break - - - client_call_details: grpc.ClientCallDetails = self._update_client_call_details_metadata( - client_call_details, metadata + client_call_details: grpc.ClientCallDetails = ( + self._update_client_call_details_metadata( + client_call_details, metadata + ) ) return continuation(client_call_details, request) @@ -228,10 +213,48 @@ def intercept_unary_stream( """ return self._intercept(continuation, client_call_details, request) + def _append_metadata(self, metadata: MetadataType) -> MetadataType: + """Appends the version of library dependencies to the user agent. -class _AsyncMetadataInterceptor( - MetadataInterceptor -): + Args: + metadata: a list of tuples containing request metadata. + + Returns: + A list of tuples containing request metadata with the version of + library dependencies appended to the user agent. + """ + # TODO: This logic should be updated or removed once the following is + # fixed: https://github.com/googleapis/python-api-core/issues/416 + for i, metadatum_tuple in enumerate(metadata): + # Check if the user agent header key is in the current metadatum + if "x-goog-api-client" in metadatum_tuple: + # Convert the tuple to a list so it can be modified. + metadatum: List[str] = list(metadatum_tuple) + + if _GAADA: + metadatum[1] += f" gaada/{_GAADA}" + + if _PROTOBUF_VERSION: + # Check that "pb" isn't already included in the user agent. + if "pb" not in metadatum[1]: + # Append the protobuf version key value pair to the end + # of the string. + metadatum[ + 1 + ] += f" pb/{_PROTOBUF_VERSION}{_PB_IMPL_HEADER}" + + # Convert the metadatum back to a tuple. + metadatum_tuple: Tuple[str, str] = tuple(metadatum) + # Splice the metadatum back in its original position in + # order to preserve the order of the metadata list. + metadata[i] = metadatum_tuple + # Exit the loop since we already found the user agent. + break + + return metadata + + +class _AsyncMetadataInterceptor(MetadataInterceptor): """An interceptor that appends custom metadata to requests.""" async def _intercept( @@ -268,25 +291,7 @@ async def _intercept( if self.linked_customer_id_meta: metadata.append(self.linked_customer_id_meta) - # TODO: This logic should be updated or removed once the following is - # fixed: https://github.com/googleapis/python-api-core/issues/416 - for i, metadatum_tuple in enumerate(metadata): - # Check if the user agent header key is in the current metadatum - if "x-goog-api-client" in metadatum_tuple and _PROTOBUF_VERSION: - # Convert the tuple to a list so it can be modified. - metadatum: List[str] = list(metadatum_tuple) - # Check that "pb" isn't already included in the user agent. - if "pb" not in metadatum[1]: - # Append the protobuf version key value pair to the end of - # the string. - metadatum[1] += f" pb/{_PROTOBUF_VERSION}{_PB_IMPL_HEADER}" - # Convert the metadatum back to a tuple. - metadatum_tuple: Tuple[str, str] = tuple(metadatum) - # Splice the metadatum back in its original position in - # order to preserve the order of the metadata list. - metadata[i] = metadatum_tuple - # Exit the loop since we already found the user agent. - break + metadata = self._append_metadata(metadata) client_call_details: grpc.ClientCallDetails = ( self._update_client_call_details_metadata( @@ -340,20 +345,23 @@ async def intercept_unary_stream( """ return await self._intercept(continuation, client_call_details, request) + class AsyncUnaryUnaryMetadataInterceptor( _AsyncMetadataInterceptor, grpc.aio.UnaryUnaryClientInterceptor, ): """An interceptor that appends custom metadata to Unary-Unary requests.""" + class AsyncUnaryStreamMetadataInterceptor( _AsyncMetadataInterceptor, grpc.aio.UnaryStreamClientInterceptor, ): """An interceptor that appends custom metadata to Unary-Stream requests.""" + __all__ = [ "MetadataInterceptor", "AsyncUnaryUnaryMetadataInterceptor", "AsyncUnaryStreamMetadataInterceptor", -] \ No newline at end of file +] diff --git a/tests/client_test.py b/tests/client_test.py index 757d5188a..d2a6031e2 100644 --- a/tests/client_test.py +++ b/tests/client_test.py @@ -114,7 +114,6 @@ def test_get_client_kwargs_login_customer_id(self): "linked_customer_id": self.linked_customer_id, "http_proxy": None, "use_cloud_org_for_api_access": None, - "gaada": None }, ) @@ -148,7 +147,6 @@ def test_get_client_kwargs_login_customer_id_as_None(self): "linked_customer_id": None, "http_proxy": None, "use_cloud_org_for_api_access": None, - "gaada": None }, ) @@ -182,7 +180,6 @@ def test_get_client_kwargs_linked_customer_id(self): "linked_customer_id": self.linked_customer_id, "http_proxy": None, "use_cloud_org_for_api_access": None, - "gaada": None }, ) @@ -216,7 +213,6 @@ def test_get_client_kwargs_linked_customer_id_as_none(self): "login_customer_id": None, "http_proxy": None, "use_cloud_org_for_api_access": None, - "gaada": None }, ) @@ -250,7 +246,6 @@ def test_get_client_kwargs(self): "linked_customer_id": None, "http_proxy": self.http_proxy, "use_cloud_org_for_api_access": None, - "gaada": None }, ) @@ -285,7 +280,6 @@ def test_get_client_kwargs_custom_endpoint(self): "linked_customer_id": None, "http_proxy": None, "use_cloud_org_for_api_access": None, - "gaada": None }, ) @@ -300,15 +294,17 @@ def test_load_from_env(self): }, } - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials, mock.patch.dict( - os.environ, config - ) as mock_os_environ: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + mock.patch.dict(os.environ, config) as mock_os_environ, + ): Client.GoogleAdsClient.load_from_env() mock_client_init.assert_called_once_with( @@ -322,7 +318,6 @@ def test_load_from_env(self): version=None, http_proxy=None, use_cloud_org_for_api_access=None, - gaada=None ) def test_load_from_env_versioned(self): @@ -336,15 +331,17 @@ def test_load_from_env_versioned(self): }, } - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials, mock.patch.dict( - os.environ, config - ) as mock_os_environ: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + mock.patch.dict(os.environ, config) as mock_os_environ, + ): Client.GoogleAdsClient.load_from_env(version="v4") mock_client_init.assert_called_once_with( @@ -358,7 +355,6 @@ def test_load_from_env_versioned(self): version="v4", http_proxy=None, use_cloud_org_for_api_access=None, - gaada=None ) def test_load_from_dict(self): @@ -372,13 +368,16 @@ def test_load_from_dict(self): } mock_credentials_instance = mock.Mock() - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + ): Client.GoogleAdsClient.load_from_dict(config) mock_client_init.assert_called_once_with( @@ -392,7 +391,6 @@ def test_load_from_dict(self): version=None, http_proxy=None, use_cloud_org_for_api_access=None, - gaada=None ) def test_load_from_dict_versioned(self): @@ -406,13 +404,16 @@ def test_load_from_dict_versioned(self): } mock_credentials_instance = mock.Mock() - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + ): Client.GoogleAdsClient.load_from_dict(config, version="v4") mock_client_init.assert_called_once_with( @@ -426,7 +427,6 @@ def test_load_from_dict_versioned(self): version="v4", http_proxy=None, use_cloud_org_for_api_access=None, - gaada=None ) def test_load_from_string(self): @@ -440,13 +440,16 @@ def test_load_from_string(self): } mock_credentials_instance = mock.Mock() - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + ): Client.GoogleAdsClient.load_from_string(yaml.dump(config)) mock_client_init.assert_called_once_with( @@ -460,7 +463,6 @@ def test_load_from_string(self): version=None, http_proxy=None, use_cloud_org_for_api_access=None, - gaada=None ) def test_load_from_string_versioned(self): @@ -474,13 +476,16 @@ def test_load_from_string_versioned(self): } mock_credentials_instance = mock.Mock() - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + ): Client.GoogleAdsClient.load_from_string( yaml.dump(config), version="v4" ) @@ -496,7 +501,6 @@ def test_load_from_string_versioned(self): version="v4", http_proxy=None, use_cloud_org_for_api_access=None, - gaada=None ) def test_get_service(self): @@ -506,7 +510,9 @@ def test_get_service(self): # Retrieve list of all the services that exist under the # {version}/services/services directory. service_dir_names = [ - name for name in os.listdir(services_filepath) if name.endswith("_service") + name + for name in os.listdir(services_filepath) + if name.endswith("_service") ] client = self._create_test_client(version=ver) @@ -514,13 +520,15 @@ def test_get_service(self): for dir_name in service_dir_names: # Converts from snake case to title case, for example: # google_ads_service --> GoogleAdsService - service_name = ''.join( + service_name = "".join( [part.capitalize() for part in dir_name.split("_")] ) # Load each service module svc = client.get_service(service_name) - self.assertEqual(svc.__class__.__name__, f"{service_name}Client") + self.assertEqual( + svc.__class__.__name__, f"{service_name}Client" + ) def test_get_async_service(self): # Retrieve service names for all defined service clients. @@ -529,7 +537,9 @@ def test_get_async_service(self): # Retrieve list of all the services that exist under the # {version}/services/services directory. service_dir_names = [ - name for name in os.listdir(services_filepath) if name.endswith("_service") + name + for name in os.listdir(services_filepath) + if name.endswith("_service") ] client = self._create_test_client(version=ver) @@ -537,14 +547,15 @@ def test_get_async_service(self): for dir_name in service_dir_names: # Converts from snake case to title case, for example: # google_ads_service --> GoogleAdsService - service_name = ''.join( + service_name = "".join( [part.capitalize() for part in dir_name.split("_")] ) # Load each service module svc = client.get_service(service_name, is_async=True) - self.assertEqual(svc.__class__.__name__, f"{service_name}AsyncClient") - + self.assertEqual( + svc.__class__.__name__, f"{service_name}AsyncClient" + ) def test_get_service_custom_endpoint(self): service_name = "GoogleAdsService" @@ -647,11 +658,12 @@ def test_get_type_protobuf_proto(self): def test_init_no_logging_config(self): """Should call logging.config.dictConfig if logging config exists.""" - with mock.patch( - "logging.config.dictConfig" - ) as mock_dictConfig, mock.patch.object( - Client.oauth2, "get_installed_app_credentials" - ) as mock_credentials: + with ( + mock.patch("logging.config.dictConfig") as mock_dictConfig, + mock.patch.object( + Client.oauth2, "get_installed_app_credentials" + ) as mock_credentials, + ): mock_credentials_instance = mock_credentials.return_value mock_credentials_instance.refresh_token = self.refresh_token mock_credentials_instance.client_id = self.client_id @@ -664,11 +676,12 @@ def test_init_no_logging_config(self): def test_init_with_logging_config(self): """Configured LoggingInterceptor should call logging.dictConfig.""" config = {"test": True} - with mock.patch( - "logging.config.dictConfig" - ) as mock_dictConfig, mock.patch.object( - Client.oauth2, "get_installed_app_credentials" - ) as mock_credentials: + with ( + mock.patch("logging.config.dictConfig") as mock_dictConfig, + mock.patch.object( + Client.oauth2, "get_installed_app_credentials" + ) as mock_credentials, + ): mock_credentials_instance = mock_credentials.return_value mock_credentials_instance.refresh_token = self.refresh_token mock_credentials_instance.client_id = self.client_id @@ -871,15 +884,17 @@ def test_load_http_proxy_from_env(self): }, } - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials, mock.patch.dict( - os.environ, config - ) as mock_os_environ: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + mock.patch.dict(os.environ, config) as mock_os_environ, + ): Client.GoogleAdsClient.load_from_env() mock_client_init.assert_called_once_with( @@ -893,7 +908,6 @@ def test_load_http_proxy_from_env(self): version=None, http_proxy=self.http_proxy, use_cloud_org_for_api_access=None, - gaada=None ) def test_load_http_proxy_from_dict(self): @@ -908,13 +922,16 @@ def test_load_http_proxy_from_dict(self): } mock_credentials_instance = mock.Mock() - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + ): Client.GoogleAdsClient.load_from_dict(config) mock_client_init.assert_called_once_with( @@ -928,7 +945,6 @@ def test_load_http_proxy_from_dict(self): version=None, http_proxy=self.http_proxy, use_cloud_org_for_api_access=None, - gaada=None ) def test_load_http_proxy_from_string(self): @@ -943,13 +959,16 @@ def test_load_http_proxy_from_string(self): } mock_credentials_instance = mock.Mock() - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + ): Client.GoogleAdsClient.load_from_string(yaml.dump(config)) mock_client_init.assert_called_once_with( @@ -963,13 +982,15 @@ def test_load_http_proxy_from_string(self): version=None, http_proxy=self.http_proxy, use_cloud_org_for_api_access=None, - gaada=None ) def test_client_info_package_not_found(self): - with mock.patch("google.ads.googleads.client.metadata.version") as mock_version: + with mock.patch( + "google.ads.googleads.client.metadata.version" + ) as mock_version: mock_version.side_effect = Client.metadata.PackageNotFoundError from importlib import reload + reload(Client) self.assertIsInstance(Client._CLIENT_INFO, Client.ClientInfo) self.assertIsNone(Client._CLIENT_INFO.client_library_version) @@ -1007,13 +1028,16 @@ def test_load_http_proxy_from_storage(self): self.fs.create_file(file_path, contents=yaml.safe_dump(config)) mock_credentials_instance = mock.Mock() - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + ): Client.GoogleAdsClient.load_from_storage() mock_credentials.assert_called_once_with( config.get("client_id"), @@ -1032,7 +1056,6 @@ def test_load_http_proxy_from_storage(self): version=None, http_proxy=self.http_proxy, use_cloud_org_for_api_access=None, - gaada=None ) def test_load_from_storage(self): @@ -1049,13 +1072,16 @@ def test_load_from_storage(self): self.fs.create_file(file_path, contents=yaml.safe_dump(config)) mock_credentials_instance = mock.Mock() - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + ): Client.GoogleAdsClient.load_from_storage() mock_credentials.assert_called_once_with( config.get("client_id"), @@ -1074,7 +1100,6 @@ def test_load_from_storage(self): version=None, http_proxy=None, use_cloud_org_for_api_access=None, - gaada=None ) def test_load_from_storage_versioned(self): @@ -1091,13 +1116,16 @@ def test_load_from_storage_versioned(self): self.fs.create_file(file_path, contents=yaml.safe_dump(config)) mock_credentials_instance = mock.Mock() - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + ): Client.GoogleAdsClient.load_from_storage(version="v4") mock_credentials.assert_called_once_with( config.get("client_id"), @@ -1116,7 +1144,6 @@ def test_load_from_storage_versioned(self): version="v4", http_proxy=None, use_cloud_org_for_api_access=None, - gaada=None ) def test_load_from_storage_login_cid_int(self): @@ -1135,13 +1162,16 @@ def test_load_from_storage_login_cid_int(self): self.fs.create_file(file_path, contents=yaml.safe_dump(config)) mock_credentials_instance = mock.Mock() - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + ): Client.GoogleAdsClient.load_from_storage() mock_credentials.assert_called_once_with( config.get("client_id"), @@ -1160,7 +1190,6 @@ def test_load_from_storage_login_cid_int(self): version=None, http_proxy=None, use_cloud_org_for_api_access=None, - gaada=None ) def test_load_from_storage_custom_path(self): @@ -1177,12 +1206,15 @@ def test_load_from_storage_custom_path(self): self.fs.create_file(file_path, contents=yaml.safe_dump(config)) mock_credentials_instance = mock.Mock() - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_installed_app_credentials", - return_value=mock_credentials_instance, + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_installed_app_credentials", + return_value=mock_credentials_instance, + ), ): Client.GoogleAdsClient.load_from_storage(path=file_path) mock_client_init.assert_called_once_with( @@ -1196,7 +1228,6 @@ def test_load_from_storage_custom_path(self): version=None, http_proxy=None, use_cloud_org_for_api_access=None, - gaada=None ) def test_load_from_storage_file_not_found(self): @@ -1235,13 +1266,16 @@ def test_load_from_storage_service_account_config(self): self.fs.create_file(file_path, contents=yaml.safe_dump(config)) mock_credentials_instance = mock.Mock() - with mock.patch.object( - Client.GoogleAdsClient, "__init__", return_value=None - ) as mock_client_init, mock.patch.object( - Client.oauth2, - "get_service_account_credentials", - return_value=mock_credentials_instance, - ) as mock_credentials: + with ( + mock.patch.object( + Client.GoogleAdsClient, "__init__", return_value=None + ) as mock_client_init, + mock.patch.object( + Client.oauth2, + "get_service_account_credentials", + return_value=mock_credentials_instance, + ) as mock_credentials, + ): Client.GoogleAdsClient.load_from_storage(version=latest_version) mock_credentials.assert_called_once_with( config.get("json_key_file_path"), @@ -1259,5 +1293,4 @@ def test_load_from_storage_service_account_config(self): version=latest_version, http_proxy=None, use_cloud_org_for_api_access=None, - gaada=None ) diff --git a/tests/config_test.py b/tests/config_test.py index 819268f8b..9697ff50e 100644 --- a/tests/config_test.py +++ b/tests/config_test.py @@ -320,17 +320,6 @@ def test_load_from_dict_logging(self): } self.assertEqual(config.load_from_dict(config_data), config_data) - def test_load_from_dict_gaada(self): - """Should load "gaada" config from dict.""" - config_data = { - **self.default_dict_config, - **{ - "gaada": "1.6.0", - }, - } - result = config.load_from_dict(config_data) - self.assertEqual(result["gaada"], "1.6.0") - def test_load_from_dict_secondary_service_account_keys(self): """Should convert secondary keys to primary keys.""" config_data = { @@ -387,7 +376,7 @@ def test_load_from_env(self, config_spy): "linked_customer_id": self.linked_customer_id, "json_key_file_path": self.json_key_file_path, "impersonated_email": self.impersonated_email, - "use_application_default_credentials": self.use_application_default_credentials + "use_application_default_credentials": self.use_application_default_credentials, }, ) config_spy.assert_called_once() @@ -457,13 +446,16 @@ def test_load_from_env_config_file_path_added_vars(self): }, } - with mock.patch("os.environ", environ), mock.patch.object( - # Mock load_from_yaml_file return value so it returns - # a default dict config that passes validation - config, - "load_from_yaml_file", - return_value=self.default_dict_config, - ) as spy: + with ( + mock.patch("os.environ", environ), + mock.patch.object( + # Mock load_from_yaml_file return value so it returns + # a default dict config that passes validation + config, + "load_from_yaml_file", + return_value=self.default_dict_config, + ) as spy, + ): # Assert that the config values were retrieved from the yaml # file and not from environment variables. result = config.load_from_env() @@ -592,7 +584,7 @@ def test_validate_login_customer_id_invalid(self): def test_validate_login_customer_id_unicode(self): self.assertRaises( - ValueError, config.validate_login_customer_id, "1230\u00B2" + ValueError, config.validate_login_customer_id, "1230\u00b2" ) def test_validate_login_customer_id_embedded(self): @@ -675,35 +667,6 @@ def test_disambiguate_string_bool_raises_value_error(self): def test_disambiguate_string_bool_raises_type_error(self): self.assertRaises(TypeError, config.disambiguate_string_bool, {}) - def test_load_from_env_gaada(self): - """Should load ads api assistant flag from environment when specified""" - environ = { - **self.default_env_var_config, - **{ - "GOOGLE_ADS_GAADA": "1.6.0", - }, - } - - with mock.patch("os.environ", environ): - results = config.load_from_env() - self.assertEqual( - results["gaada"], - "1.6.0", - ) - - def test_load_from_yaml_file_gaada(self): - """Should load "gaada" config from a yaml.""" - self._create_mock_yaml({"gaada": "1.6.0"}) - - result = config.load_from_yaml_file() - self.assertEqual(result["gaada"], "1.6.0") - - def test_load_from_yaml_file_gaada_not_set(self): - """Should set "gaada" as False when not set.""" - self._create_mock_yaml({}) - result = config.load_from_yaml_file() - self.assertEqual(result.get("gaada"), None) - def test_load_from_env_use_cloud_org_for_api_access(self): """Should load api access flag from environment when specified""" environ = {