Skip to content

Commit 0c6cff3

Browse files
authored
Fix bug related to augmenting client call details metatadata (#17)
Use public interface for re-creating ClientCallDetails with updated metadata in interceptor
1 parent 951da24 commit 0c6cff3

File tree

5 files changed

+103
-6
lines changed

5 files changed

+103
-6
lines changed

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
* 0.5.1:
2+
- Fix bug related to usage of private grpc._interceptor._ClientCallDetails class
3+
14
* 0.5.0:
25
- Google Ads v0_6 release.
36
- Updating add_campaign_targeting_criteria.py example to add

google/ads/google_ads/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@
1818
import google.ads.google_ads.errors
1919

2020

21-
VERSION = '0.4.0'
21+
VERSION = '0.5.1'

google/ads/google_ads/client.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import logging
1717
import os
1818
import yaml
19+
from collections import namedtuple
1920

2021
import google.api_core.grpc_helpers
2122
import google.auth.transport.requests
@@ -346,6 +347,14 @@ def __init__(self, developer_token, login_customer_id):
346347
('login-customer-id', login_customer_id) if login_customer_id
347348
else None)
348349

350+
def _update_client_call_details_metadata(
351+
self, client_call_details, metadata):
352+
client_call_details = _ClientCallDetails(
353+
client_call_details.method, client_call_details.timeout, metadata,
354+
client_call_details.credentials)
355+
356+
return client_call_details
357+
349358
def intercept_unary_unary(self, continuation, client_call_details, request):
350359
"""Intercepts and appends custom metadata.
351360
@@ -361,14 +370,22 @@ def intercept_unary_unary(self, continuation, client_call_details, request):
361370
if self.login_customer_id_meta:
362371
metadata.append(self.login_customer_id_meta)
363372

364-
client_call_details = grpc._interceptor._ClientCallDetails(
365-
client_call_details.method, client_call_details.timeout, metadata,
366-
client_call_details.credentials
367-
)
373+
client_call_details = self._update_client_call_details_metadata(
374+
client_call_details,
375+
metadata)
368376

369377
return continuation(client_call_details, request)
370378

371379

380+
class _ClientCallDetails(
381+
namedtuple(
382+
'_ClientCallDetails',
383+
('method', 'timeout', 'metadata', 'credentials')),
384+
grpc.ClientCallDetails):
385+
"""An wrapper class for initializing a new ClientCallDetails instance."""
386+
pass
387+
388+
372389
def _get_version(name):
373390
"""Returns the given API version.
374391

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
setup(
3535
name='google-ads',
36-
version='0.5.0',
36+
version='0.5.1',
3737
author='Google LLC',
3838
author_email='[email protected]',
3939
classifiers=[

tests/client_test.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,3 +304,80 @@ def test_get_type_invalid_version(self):
304304
self.assertRaises(
305305
ValueError, google.ads.google_ads.client.GoogleAdsClient.get_type,
306306
'GoogleAdsFailure', version='v0_bad')
307+
308+
309+
class MetadataInterceptorTest(TestCase):
310+
311+
def setUp(self):
312+
self.mock_developer_token = '1234567890'
313+
self.mock_login_customer_id = '0987654321'
314+
315+
def test_init(self):
316+
interceptor = google.ads.google_ads.client.MetadataInterceptor(
317+
self.mock_developer_token,
318+
self.mock_login_customer_id)
319+
320+
self.assertEqual(
321+
interceptor.developer_token_meta,
322+
('developer-token', self.mock_developer_token))
323+
324+
self.assertEqual(
325+
interceptor.login_customer_id_meta,
326+
('login-customer-id', self.mock_login_customer_id)
327+
)
328+
329+
def test_init_no_login_customer_id(self):
330+
interceptor = google.ads.google_ads.client.MetadataInterceptor(
331+
self.mock_developer_token,
332+
None)
333+
334+
self.assertEqual(
335+
interceptor.developer_token_meta,
336+
('developer-token', self.mock_developer_token))
337+
338+
self.assertEqual(
339+
interceptor.login_customer_id_meta,
340+
None
341+
)
342+
343+
def test_update_client_call_details_metadata(self):
344+
interceptor = google.ads.google_ads.client.MetadataInterceptor(
345+
self.mock_developer_token,
346+
self.mock_login_customer_id)
347+
348+
mock_metadata = list([('test-key', 'test-value')])
349+
mock_client_call_details = mock.Mock()
350+
351+
client_call_details = interceptor._update_client_call_details_metadata(
352+
mock_client_call_details, mock_metadata)
353+
354+
self.assertEqual(client_call_details.metadata, mock_metadata)
355+
356+
def test_intercept_unary_unary(self):
357+
interceptor = google.ads.google_ads.client.MetadataInterceptor(
358+
self.mock_developer_token,
359+
self.mock_login_customer_id)
360+
361+
mock_continuation = mock.Mock(return_value=None)
362+
mock_client_call_details = mock.Mock()
363+
mock_client_call_details.method = 'test/method'
364+
mock_client_call_details.timeout = 5
365+
mock_client_call_details.metadata = [('apples', 'oranges')]
366+
mock_request = mock.Mock()
367+
368+
with mock.patch.object(
369+
interceptor,
370+
'_update_client_call_details_metadata',
371+
wraps=interceptor._update_client_call_details_metadata
372+
) as mock_updater:
373+
interceptor.intercept_unary_unary(
374+
mock_continuation,
375+
mock_client_call_details,
376+
mock_request)
377+
378+
mock_updater.assert_called_once_with(
379+
mock_client_call_details, [mock_client_call_details.metadata[0],
380+
interceptor.developer_token_meta,
381+
interceptor.login_customer_id_meta])
382+
383+
mock_continuation.assert_called_once()

0 commit comments

Comments
 (0)