diff --git a/error_reporting/google/cloud/error_reporting/_gapic.py b/error_reporting/google/cloud/error_reporting/_gapic.py index 227092f9bfb0..b1925ff6a491 100644 --- a/error_reporting/google/cloud/error_reporting/_gapic.py +++ b/error_reporting/google/cloud/error_reporting/_gapic.py @@ -14,15 +14,10 @@ """GAX wrapper for Error Reporting API requests.""" -from google.api_core.gapic_v1 import client_info - -from google.cloud.error_reporting import __version__ from google.cloud.errorreporting_v1beta1.gapic import report_errors_service_client from google.cloud.errorreporting_v1beta1.proto import report_errors_service_pb2 from google.protobuf.json_format import ParseDict -_CLIENT_INFO = client_info.ClientInfo(client_library_version=__version__) - def make_report_error_api(client): """Create an instance of the gapic Logging API. @@ -33,10 +28,10 @@ def make_report_error_api(client): :rtype: :class:_ErrorReportingGapicApi :returns: An Error Reporting API instance. """ - gax_client = report_errors_service_client.ReportErrorsServiceClient( - credentials=client._credentials, client_info=_CLIENT_INFO + gapic_api = report_errors_service_client.ReportErrorsServiceClient( + credentials=client._credentials, client_info=client._client_info ) - return _ErrorReportingGapicApi(gax_client, client.project) + return _ErrorReportingGapicApi(gapic_api, client.project) class _ErrorReportingGapicApi(object): diff --git a/error_reporting/google/cloud/error_reporting/_logging.py b/error_reporting/google/cloud/error_reporting/_logging.py index b09488914ce9..5eaa4693c96f 100644 --- a/error_reporting/google/cloud/error_reporting/_logging.py +++ b/error_reporting/google/cloud/error_reporting/_logging.py @@ -45,11 +45,20 @@ class _ErrorReportingLoggingAPI(object): ``credentials`` for the current object. This parameter should be considered private, and could change in the future. + + :type client_info: + :class:`google.api_core.client_info.ClientInfo` or + :class:`google.api_core.gapic_v1.client_info.ClientInfo` + :param client_info: + The client info used to send a user-agent string along with API + requests. If ``None``, then default info will be used. Generally, + you only need to set this if you're developing your own library + or partner tool. """ - def __init__(self, project, credentials=None, _http=None): + def __init__(self, project, credentials=None, _http=None, client_info=None): self.logging_client = google.cloud.logging.client.Client( - project, credentials, _http=_http + project, credentials, _http=_http, client_info=client_info ) def report_error_event(self, error_report): diff --git a/error_reporting/google/cloud/error_reporting/client.py b/error_reporting/google/cloud/error_reporting/client.py index 699fbdb7d97f..e2c0e4261c52 100644 --- a/error_reporting/google/cloud/error_reporting/client.py +++ b/error_reporting/google/cloud/error_reporting/client.py @@ -17,21 +17,27 @@ import os import traceback +import six + try: from google.cloud.error_reporting._gapic import make_report_error_api - - _HAVE_GRPC = True except ImportError: # pragma: NO COVER + from google.api_core import ciient_info # noqa + _HAVE_GRPC = False +else: + from google.api_core.gapic_v1 import client_info + + _HAVE_GRPC = True from google.cloud.client import ClientWithProject +from google.cloud.error_reporting import __version__ from google.cloud.error_reporting._logging import _ErrorReportingLoggingAPI from google.cloud.environment_vars import DISABLE_GRPC -import six - _DISABLE_GRPC = os.getenv(DISABLE_GRPC, False) _USE_GRPC = _HAVE_GRPC and not _DISABLE_GRPC +_CLIENT_INFO = client_info.ClientInfo(client_library_version=__version__) class HTTPContext(object): @@ -128,6 +134,15 @@ class Client(ClientWithProject): This parameter should be considered private, and could change in the future. + :type client_info: + :class:`google.api_core.client_info.ClientInfo` or + :class:`google.api_core.gapic_v1.client_info.ClientInfo` + :param client_info: + The client info used to send a user-agent string along with API + requests. If ``None``, then default info will be used. Generally, + you only need to set this if you're developing your own library + or partner tool. + :raises: :class:`ValueError` if the project is neither passed in nor set in the environment. """ @@ -142,6 +157,7 @@ def __init__( _http=None, service=None, version=None, + client_info=_CLIENT_INFO, _use_grpc=None, ): super(Client, self).__init__( @@ -151,6 +167,8 @@ def __init__( self.service = service if service else self.DEFAULT_SERVICE self.version = version + self._client_info = client_info + if _use_grpc is None: self._use_grpc = _USE_GRPC else: @@ -177,7 +195,7 @@ def report_errors_api(self): self._report_errors_api = make_report_error_api(self) else: self._report_errors_api = _ErrorReportingLoggingAPI( - self.project, self._credentials, self._http + self.project, self._credentials, self._http, self._client_info ) return self._report_errors_api diff --git a/error_reporting/tests/unit/test__gapic.py b/error_reporting/tests/unit/test__gapic.py index 2b6dbbb37be2..836f46b82495 100644 --- a/error_reporting/tests/unit/test__gapic.py +++ b/error_reporting/tests/unit/test__gapic.py @@ -18,37 +18,31 @@ class Test_make_report_error_api(unittest.TestCase): - def test_make_report_error_api(self): - from google.cloud.errorreporting_v1beta1.gapic import ( - report_errors_service_client, - ) - + @staticmethod + def _call_fut(client): from google.cloud.error_reporting._gapic import make_report_error_api - client = mock.Mock( - _credentials=mock.sentinel.credentials, - project="prahj-ekt", - spec=["project", "_credentials"], - ) + return make_report_error_api(client) - # Mock out the constructor for the GAPIC client. - ServiceClient = report_errors_service_client.ReportErrorsServiceClient - with mock.patch.object(ServiceClient, "__init__") as resc: - resc.return_value = None + def test_make_report_error_api(self): + client = mock.Mock(spec=["project", "_credentials", "_client_info"]) - # Call the function being tested. - report_error_client = make_report_error_api(client) + # Call the function being tested. + patch = mock.patch( + "google.cloud.errorreporting_v1beta1." + "gapic.report_errors_service_client.ReportErrorsServiceClient" + ) - # Assert that the arguments to the GAPIC constructor appear - # to be correct. - resc.assert_called_once() - _, _, kwargs = resc.mock_calls[0] - self.assertEqual(kwargs["credentials"], mock.sentinel.credentials) - self.assertIsNotNone(kwargs["client_info"]) + with patch as patched: + report_error_client = self._call_fut(client) # Assert that the final error client has the project in # the expected location. self.assertIs(report_error_client._project, client.project) + self.assertIs(report_error_client._gapic_api, patched.return_value) + patched.assert_called_once_with( + credentials=client._credentials, client_info=client._client_info + ) class Test_ErrorReportingGapicApi(unittest.TestCase): diff --git a/error_reporting/tests/unit/test__logging.py b/error_reporting/tests/unit/test__logging.py index 674a3a9ee726..e2b0638b986e 100644 --- a/error_reporting/tests/unit/test__logging.py +++ b/error_reporting/tests/unit/test__logging.py @@ -27,26 +27,41 @@ class Test_ErrorReportingLoggingAPI(unittest.TestCase): PROJECT = "PROJECT" - def _make_one(self, project, credentials): + def _make_one(self, project, credentials, **kw): from google.cloud.error_reporting._logging import _ErrorReportingLoggingAPI - return _ErrorReportingLoggingAPI(project, credentials) + return _ErrorReportingLoggingAPI(project, credentials, **kw) - def test_constructor(self): + @mock.patch("google.cloud.logging.client.Client") + def test_ctor_defaults(self, mocked_cls): credentials = _make_credentials() + logging_api = self._make_one(self.PROJECT, credentials) - self.assertEqual( - logging_api.logging_client._connection.credentials, credentials + self.assertIs(logging_api.logging_client, mocked_cls.return_value) + mocked_cls.assert_called_once_with( + self.PROJECT, credentials, _http=None, client_info=None + ) + + @mock.patch("google.cloud.logging.client.Client") + def test_ctor_explicit(self, mocked_cls): + credentials = _make_credentials() + http = mock.Mock() + client_info = mock.Mock() + + logging_api = self._make_one( + self.PROJECT, credentials, _http=http, client_info=client_info + ) + + self.assertIs(logging_api.logging_client, mocked_cls.return_value) + mocked_cls.assert_called_once_with( + self.PROJECT, credentials, _http=http, client_info=client_info ) - self.assertEqual(logging_api.logging_client.project, self.PROJECT) @mock.patch("google.cloud.logging.client.Client") def test_report_error_event(self, mocked_cls): credentials = _make_credentials() logging_api = self._make_one(self.PROJECT, credentials) - mocked_cls.assert_called_once_with(self.PROJECT, credentials, _http=None) - self.assertIs(logging_api.logging_client, mocked_cls.return_value) logger = mock.Mock(spec=["log_struct"]) logging_api.logging_client.logger.return_value = logger diff --git a/error_reporting/tests/unit/test_client.py b/error_reporting/tests/unit/test_client.py index 458db5136e11..5e4dc925a65f 100644 --- a/error_reporting/tests/unit/test_client.py +++ b/error_reporting/tests/unit/test_client.py @@ -53,26 +53,72 @@ def _get_report_payload(self, error_api): return positional[0] @mock.patch("google.cloud.client._determine_default_project") - def test_ctor_default(self, default_mock): + def test_ctor_defaults(self, default_mock): + from google.api_core.client_info import ClientInfo + credentials = _make_credentials() default_mock.return_value = "foo" client = self._make_one(credentials=credentials) self.assertEqual(client.service, client.DEFAULT_SERVICE) self.assertEqual(client.version, None) + self.assertIsInstance(client._client_info, ClientInfo) default_mock.assert_called_once_with(None) - def test_ctor_params(self): + def test_ctor_explicit(self): credentials = _make_credentials() + client_info = mock.Mock() client = self._make_one( project=self.PROJECT, credentials=credentials, service=self.SERVICE, version=self.VERSION, + client_info=client_info, ) self.assertEqual(client.service, self.SERVICE) self.assertEqual(client.version, self.VERSION) + self.assertIs(client._client_info, client_info) + + def test_report_errors_api_already(self): + credentials = _make_credentials() + client = self._make_one(project=self.PROJECT, credentials=credentials) + client._report_errors_api = already = mock.Mock() + self.assertIs(client.report_errors_api, already) + + def test_report_errors_api_wo_grpc(self): + credentials = _make_credentials() + client_info = mock.Mock() + http = mock.Mock() + client = self._make_one( + project=self.PROJECT, + credentials=credentials, + client_info=client_info, + _http=http, + _use_grpc=False, + ) + patch = mock.patch( + "google.cloud.error_reporting.client._ErrorReportingLoggingAPI" + ) + + with patch as patched: + api = client.report_errors_api + + self.assertIs(api, patched.return_value) + patched.assert_called_once_with(self.PROJECT, credentials, http, client_info) + + def test_report_errors_api_w_grpc(self): + credentials = _make_credentials() + client = self._make_one( + project=self.PROJECT, credentials=credentials, _use_grpc=True + ) + patch = mock.patch("google.cloud.error_reporting.client.make_report_error_api") + + with patch as patched: + api = client.report_errors_api + + self.assertIs(api, patched.return_value) + patched.assert_called_once_with(client) - def test_report_exception_with_gax(self): + def test_report_exception_with_grpc(self): credentials = _make_credentials() client = self._make_one(project=self.PROJECT, credentials=credentials) @@ -89,7 +135,7 @@ def test_report_exception_with_gax(self): self.assertIn("test_report", payload["message"]) self.assertIn("test_client.py", payload["message"]) - def test_report_exception_wo_gax(self): + def test_report_exception_wo_grpc(self): credentials = _make_credentials() client = self._make_one( project=self.PROJECT, credentials=credentials, _use_grpc=False