diff --git a/googleapiclient/discovery.py b/googleapiclient/discovery.py index a8f59bca5ab..f7bbd77763c 100644 --- a/googleapiclient/discovery.py +++ b/googleapiclient/discovery.py @@ -1170,9 +1170,11 @@ def method(self, **kwargs): elif "response" not in methodDesc: model = RawModel() + api_version = methodDesc.get("apiVersion", None) + headers = {} headers, params, query, body = model.request( - headers, actual_path_params, actual_query_params, body_value + headers, actual_path_params, actual_query_params, body_value, api_version ) expanded_url = uritemplate.expand(pathUrl, params) diff --git a/googleapiclient/model.py b/googleapiclient/model.py index 4ba27522357..dee1cb7f377 100644 --- a/googleapiclient/model.py +++ b/googleapiclient/model.py @@ -27,10 +27,18 @@ import logging import platform import urllib +import warnings from googleapiclient import version as googleapiclient_version from googleapiclient.errors import HttpError +try: + from google.api_core.version_header import API_VERSION_METADATA_KEY + + HAS_API_VERSION = True +except ImportError: + HAS_API_VERSION = False + _LIBRARY_VERSION = googleapiclient_version.__version__ _PY_VERSION = platform.python_version() @@ -121,7 +129,7 @@ def _log_request(self, headers, path_params, query, body): LOGGER.info("query: %s", query) LOGGER.info("--request-end--") - def request(self, headers, path_params, query_params, body_value): + def request(self, headers, path_params, query_params, body_value, api_version=None): """Updates outgoing requests with a serialized body. Args: @@ -129,7 +137,10 @@ def request(self, headers, path_params, query_params, body_value): path_params: dict, parameters that appear in the request path query_params: dict, parameters that appear in the query body_value: object, the request body as a Python object, which must be - serializable by json. + serializable by json. + api_version: str, The precise API version represented by this request, + which will result in an API Version header being sent along with the + HTTP request. Returns: A tuple of (headers, path_params, query, body) @@ -155,6 +166,15 @@ def request(self, headers, path_params, query_params, body_value): _PY_VERSION, ) + if api_version and HAS_API_VERSION: + headers[API_VERSION_METADATA_KEY] = api_version + elif api_version: + warnings.warn( + "The `api_version` argument is ignored as a newer version of " + "`google-api-core` is required to use this feature." + "Please upgrade `google-api-core` to 2.19.0 or newer." + ) + if body_value is not None: headers["content-type"] = self.content_type body_value = self.serialize(body_value) diff --git a/tests/test_json_model.py b/tests/test_json_model.py index a34cd6d94b5..1bd75e50850 100644 --- a/tests/test_json_model.py +++ b/tests/test_json_model.py @@ -35,6 +35,13 @@ import googleapiclient.model from googleapiclient.model import JsonModel +try: + from google.api_core.version_header import API_VERSION_METADATA_KEY + + HAS_API_VERSION = True +except ImportError: + HAS_API_VERSION = False + _LIBRARY_VERSION = googleapiclient_version.__version__ CSV_TEXT_MOCK = "column1,column2,column3\nstring1,1.2,string2" @@ -172,6 +179,29 @@ def test_x_goog_api_client(self): + platform.python_version(), ) + @unittest.skipIf( + not HAS_API_VERSION, + "Skip this test when an older version of google-api-core is used", + ) + def test_x_goog_api_version(self): + model = JsonModel(data_wrapper=False) + + # test header composition for clients that wrap discovery + headers = {} + path_params = {} + query_params = {} + body = {} + api_version = "20240401" + + headers, _, _, body = model.request( + headers, path_params, query_params, body, api_version + ) + + self.assertEqual( + headers[API_VERSION_METADATA_KEY], + api_version, + ) + def test_bad_response(self): model = JsonModel(data_wrapper=False) resp = httplib2.Response({"status": "401"})