Skip to content

Commit

Permalink
Fix bug related to augmenting client call details metatadata (#17)
Browse files Browse the repository at this point in the history
Use public interface for re-creating ClientCallDetails with updated metadata in interceptor
  • Loading branch information
BenRKarl authored Dec 20, 2018
1 parent 951da24 commit 0c6cff3
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 6 deletions.
3 changes: 3 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
* 0.5.1:
- Fix bug related to usage of private grpc._interceptor._ClientCallDetails class

* 0.5.0:
- Google Ads v0_6 release.
- Updating add_campaign_targeting_criteria.py example to add
Expand Down
2 changes: 1 addition & 1 deletion google/ads/google_ads/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@
import google.ads.google_ads.errors


VERSION = '0.4.0'
VERSION = '0.5.1'
25 changes: 21 additions & 4 deletions google/ads/google_ads/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import logging
import os
import yaml
from collections import namedtuple

import google.api_core.grpc_helpers
import google.auth.transport.requests
Expand Down Expand Up @@ -346,6 +347,14 @@ def __init__(self, developer_token, login_customer_id):
('login-customer-id', login_customer_id) if login_customer_id
else None)

def _update_client_call_details_metadata(
self, client_call_details, metadata):
client_call_details = _ClientCallDetails(
client_call_details.method, client_call_details.timeout, metadata,
client_call_details.credentials)

return client_call_details

def intercept_unary_unary(self, continuation, client_call_details, request):
"""Intercepts and appends custom metadata.
Expand All @@ -361,14 +370,22 @@ def intercept_unary_unary(self, continuation, client_call_details, request):
if self.login_customer_id_meta:
metadata.append(self.login_customer_id_meta)

client_call_details = grpc._interceptor._ClientCallDetails(
client_call_details.method, client_call_details.timeout, metadata,
client_call_details.credentials
)
client_call_details = self._update_client_call_details_metadata(
client_call_details,
metadata)

return continuation(client_call_details, request)


class _ClientCallDetails(
namedtuple(
'_ClientCallDetails',
('method', 'timeout', 'metadata', 'credentials')),
grpc.ClientCallDetails):
"""An wrapper class for initializing a new ClientCallDetails instance."""
pass


def _get_version(name):
"""Returns the given API version.
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

setup(
name='google-ads',
version='0.5.0',
version='0.5.1',
author='Google LLC',
author_email='googleapis-packages@google.com',
classifiers=[
Expand Down
77 changes: 77 additions & 0 deletions tests/client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,3 +304,80 @@ def test_get_type_invalid_version(self):
self.assertRaises(
ValueError, google.ads.google_ads.client.GoogleAdsClient.get_type,
'GoogleAdsFailure', version='v0_bad')


class MetadataInterceptorTest(TestCase):

def setUp(self):
self.mock_developer_token = '1234567890'
self.mock_login_customer_id = '0987654321'

def test_init(self):
interceptor = google.ads.google_ads.client.MetadataInterceptor(
self.mock_developer_token,
self.mock_login_customer_id)

self.assertEqual(
interceptor.developer_token_meta,
('developer-token', self.mock_developer_token))

self.assertEqual(
interceptor.login_customer_id_meta,
('login-customer-id', self.mock_login_customer_id)
)

def test_init_no_login_customer_id(self):
interceptor = google.ads.google_ads.client.MetadataInterceptor(
self.mock_developer_token,
None)

self.assertEqual(
interceptor.developer_token_meta,
('developer-token', self.mock_developer_token))

self.assertEqual(
interceptor.login_customer_id_meta,
None
)

def test_update_client_call_details_metadata(self):
interceptor = google.ads.google_ads.client.MetadataInterceptor(
self.mock_developer_token,
self.mock_login_customer_id)

mock_metadata = list([('test-key', 'test-value')])
mock_client_call_details = mock.Mock()

client_call_details = interceptor._update_client_call_details_metadata(
mock_client_call_details, mock_metadata)

self.assertEqual(client_call_details.metadata, mock_metadata)

def test_intercept_unary_unary(self):
interceptor = google.ads.google_ads.client.MetadataInterceptor(
self.mock_developer_token,
self.mock_login_customer_id)

mock_continuation = mock.Mock(return_value=None)
mock_client_call_details = mock.Mock()
mock_client_call_details.method = 'test/method'
mock_client_call_details.timeout = 5
mock_client_call_details.metadata = [('apples', 'oranges')]
mock_request = mock.Mock()

with mock.patch.object(
interceptor,
'_update_client_call_details_metadata',
wraps=interceptor._update_client_call_details_metadata
) as mock_updater:
interceptor.intercept_unary_unary(
mock_continuation,
mock_client_call_details,
mock_request)

mock_updater.assert_called_once_with(
mock_client_call_details, [mock_client_call_details.metadata[0],
interceptor.developer_token_meta,
interceptor.login_customer_id_meta])

mock_continuation.assert_called_once()

0 comments on commit 0c6cff3

Please sign in to comment.