Pass library and Python version in x-goog-api-client (#734)


diff --git a/googleapiclient/model.py b/googleapiclient/model.py
index dded04e..7ab80e9 100644
--- a/googleapiclient/model.py
+++ b/googleapiclient/model.py
@@ -26,12 +26,14 @@
 
 import json
 import logging
+import platform
 
 from six.moves.urllib.parse import urlencode
 
 from googleapiclient import __version__
 from googleapiclient.errors import HttpError
 
+_PY_VERSION = platform.python_version()
 
 LOGGER = logging.getLogger(__name__)
 
@@ -144,7 +146,12 @@
       headers['user-agent'] += ' '
     else:
       headers['user-agent'] = ''
-    headers['user-agent'] += 'google-api-python-client/%s (gzip)' % __version__
+    headers['user-agent'] += '(gzip)'
+    if 'x-goog-api-client' in headers:
+      headers['x-goog-api-client'] += ' '
+    else:
+      headers['x-goog-api-client'] = ''
+    headers['x-goog-api-client'] += 'gdcl/%s gl-python/%s' % (__version__, _PY_VERSION)
 
     if body_value is not None:
       headers['content-type'] = self.content_type
diff --git a/tests/test_http.py b/tests/test_http.py
index 5aaada6..b92e63f 100644
--- a/tests/test_http.py
+++ b/tests/test_http.py
@@ -485,26 +485,22 @@
     download = MediaIoBaseDownload(
         fd=self.fd, request=self.request, chunksize=3)
 
-    self.assertEqual(download._headers, {'Cache-Control':'no-store'})
+    self.assertEqual(download._headers.get('Cache-Control'), 'no-store')
 
     status, done = download.next_chunk()
 
-    result = self.fd.getvalue().decode('utf-8')
+    result = json.loads(self.fd.getvalue().decode('utf-8'))
 
-    # we abuse the internals of the object we're testing, pay no attention
-    # to the actual bytes= values here; we are just asserting that the
-    # header we added to the original request is sent up to the server
-    # on each call to next_chunk
+    # assert that that the header we added to the original request is
+    # sent up to the server on each call to next_chunk
 
-    self.assertEqual(json.loads(result),
-                     {"Cache-Control": "no-store", "range": "bytes=0-3"})
+    self.assertEqual(result.get("Cache-Control"), "no-store")
 
     download._fd = self.fd = BytesIO()
     status, done = download.next_chunk()
 
-    result = self.fd.getvalue().decode('utf-8')
-    self.assertEqual(json.loads(result),
-                     {"Cache-Control": "no-store", "range": "bytes=51-54"})
+    result = json.loads(self.fd.getvalue().decode('utf-8'))
+    self.assertEqual(result.get("Cache-Control"), "no-store")
 
   def test_media_io_base_download_handle_redirects(self):
     self.request.http = HttpMockSequence([
diff --git a/tests/test_json_model.py b/tests/test_json_model.py
index 0d1f283..006eb47 100644
--- a/tests/test_json_model.py
+++ b/tests/test_json_model.py
@@ -26,6 +26,7 @@
 import copy
 import json
 import os
+import platform
 import unittest2 as unittest
 import httplib2
 import googleapiclient.model
@@ -143,8 +144,22 @@
         headers, path_params, query_params, body)
 
     self.assertEqual(headers['user-agent'],
-        'my-test-app/1.23.4 google-api-python-client/' + __version__ +
-        ' (gzip)')
+        'my-test-app/1.23.4 (gzip)')
+
+  def test_x_goog_api_client(self):
+    model = JsonModel(data_wrapper=False)
+
+    # test header composition for cloud clients that wrap discovery
+    headers = {'x-goog-api-client': 'gccl/1.23.4'}
+    path_params = {}
+    query_params = {}
+    body = {}
+
+    headers, unused_params, unused_query, body = model.request(
+        headers, path_params, query_params, body)
+
+    self.assertEqual(headers['x-goog-api-client'],
+        'gccl/1.23.4' + ' gdcl/' + __version__ + ' gl-python/' + platform.python_version())
 
   def test_bad_response(self):
     model = JsonModel(data_wrapper=False)