diff --git a/gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/client.py.j2 b/gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/client.py.j2 index 6fd1f72621..4c5a587405 100644 --- a/gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/client.py.j2 +++ b/gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/client.py.j2 @@ -23,7 +23,7 @@ from google.oauth2 import service_account # type: ignore {% endfor -%} {% endfor -%} {% endfilter %} -from .transports.base import {{ service.name }}Transport +from .transports.base import {{ service.name }}Transport, DEFAULT_CLIENT_INFO from .transports.grpc import {{ service.name }}GrpcTransport @@ -135,6 +135,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta): credentials: credentials.Credentials = None, transport: Union[str, {{ service.name }}Transport] = None, client_options: ClientOptions = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the {{ (service.client_name|snake_case).replace('_', ' ') }}. @@ -160,6 +161,11 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta): (2) The ``client_cert_source`` property is used to provide client SSL credentials for mutual TLS transport. If not provided, the default SSL credentials will be used if present. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + 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 client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -209,6 +215,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta): host=client_options.api_endpoint, api_mtls_endpoint=client_options.api_endpoint, client_cert_source=client_options.client_cert_source, + client_info=client_info, ) diff --git a/gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/transports/base.py.j2 b/gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/transports/base.py.j2 index ba39b27abe..32e6c11f9f 100644 --- a/gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/transports/base.py.j2 +++ b/gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/transports/base.py.j2 @@ -21,13 +21,13 @@ from google.auth import credentials # type: ignore {% endfilter %} try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( '{{ api.naming.warehouse_package_name }}', ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() class {{ service.name }}Transport(metaclass=abc.ABCMeta): @@ -43,6 +43,7 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta): self, *, host: str{% if service.host %} = '{{ service.host }}'{% endif %}, credentials: credentials.Credentials = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -54,6 +55,11 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta): credentials identify the application to the service; if none are specified, the client will attempt to ascertain the credentials from the environment. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + 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 client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ':' not in host: @@ -69,9 +75,9 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta): self._credentials = credentials # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages() + self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self): + def _prep_wrapped_messages(self, client_info): # Precomputed wrapped methods self._wrapped_methods = { {% for method in service.methods.values() -%} @@ -92,7 +98,7 @@ class {{ service.name }}Transport(metaclass=abc.ABCMeta): ), {%- endif %} default_timeout={{ method.timeout }}, - client_info=_client_info, + client_info=client_info, ), {% endfor %} {# precomputed wrappers loop #} } diff --git a/gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/transports/grpc.py.j2 b/gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/transports/grpc.py.j2 index 01c77c8f23..b25817b70b 100644 --- a/gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/transports/grpc.py.j2 +++ b/gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/transports/grpc.py.j2 @@ -7,6 +7,7 @@ from google.api_core import grpc_helpers # type: ignore {%- if service.has_lro %} from google.api_core import operations_v1 # type: ignore {%- endif %} +from google.api_core import gapic_v1 # type: ignore from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -20,7 +21,7 @@ import grpc # type: ignore {{ method.output.ident.python_import }} {% endfor -%} {% endfilter %} -from .base import {{ service.name }}Transport +from .base import {{ service.name }}Transport, DEFAULT_CLIENT_INFO class {{ service.name }}GrpcTransport({{ service.name }}Transport): @@ -40,7 +41,9 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport): credentials: credentials.Credentials = None, channel: grpc.Channel = None, api_mtls_endpoint: str = None, - client_cert_source: Callable[[], Tuple[bytes, bytes]] = None) -> None: + client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: """Instantiate the transport. Args: @@ -62,6 +65,11 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport): callback to provide client SSL certificate bytes and private key bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` is None. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + 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 client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -101,7 +109,11 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport): self._stubs = {} # type: Dict[str, Callable] # Run the base constructor. - super().__init__(host=host, credentials=credentials) + super().__init__( + host=host, + credentials=credentials, + client_info=client_info, + ) @classmethod diff --git a/gapic/ads-templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2 b/gapic/ads-templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2 index fc5a596d6f..e9d47ac8ae 100644 --- a/gapic/ads-templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2 +++ b/gapic/ads-templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2 @@ -24,9 +24,7 @@ from google.api_core import future from google.api_core import operations_v1 from google.longrunning import operations_pb2 {% endif -%} -{% if service.has_pagers -%} from google.api_core import gapic_v1 -{% endif -%} {% for method in service.methods.values() -%} {% for ref_type in method.ref_types if not ((ref_type.ident.python_import.package == ('google', 'api_core') and ref_type.ident.python_import.module == 'operation') @@ -109,6 +107,7 @@ def test_{{ service.client_name|snake_case }}_client_options(): client_cert_source=None, credentials=None, host="squid.clam.whelk", + client_info=transports.base.DEFAULT_CLIENT_INFO, ) # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is @@ -122,6 +121,7 @@ def test_{{ service.client_name|snake_case }}_client_options(): client_cert_source=None, credentials=None, host=client.DEFAULT_ENDPOINT, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is @@ -135,6 +135,7 @@ def test_{{ service.client_name|snake_case }}_client_options(): client_cert_source=None, credentials=None, host=client.DEFAULT_MTLS_ENDPOINT, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is @@ -149,6 +150,7 @@ def test_{{ service.client_name|snake_case }}_client_options(): client_cert_source=client_cert_source_callback, credentials=None, host=client.DEFAULT_MTLS_ENDPOINT, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is @@ -163,6 +165,7 @@ def test_{{ service.client_name|snake_case }}_client_options(): client_cert_source=None, credentials=None, host=client.DEFAULT_MTLS_ENDPOINT, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is @@ -177,6 +180,7 @@ def test_{{ service.client_name|snake_case }}_client_options(): client_cert_source=None, credentials=None, host=client.DEFAULT_ENDPOINT, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS has @@ -197,6 +201,7 @@ def test_{{ service.client_name|snake_case }}_client_options_from_dict(): client_cert_source=None, credentials=None, host="squid.clam.whelk", + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -769,4 +774,23 @@ def test_parse_{{ message.resource_type|snake_case }}_path(): {% endwith -%} {% endfor -%} +def test_client_withDEFAULT_CLIENT_INFO(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object(transports.{{ service.name }}Transport, '_prep_wrapped_messages') as prep: + client = {{ service.client_name }}( + credentials=credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object(transports.{{ service.name }}Transport, '_prep_wrapped_messages') as prep: + transport_class = {{ service.client_name }}.get_transport_class() + transport = transport_class( + credentials=credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + {% endblock %} diff --git a/gapic/templates/%namespace/%name_%version/%sub/services/%service/async_client.py.j2 b/gapic/templates/%namespace/%name_%version/%sub/services/%service/async_client.py.j2 index 5447e1f9e6..d6882d95f4 100644 --- a/gapic/templates/%namespace/%name_%version/%sub/services/%service/async_client.py.j2 +++ b/gapic/templates/%namespace/%name_%version/%sub/services/%service/async_client.py.j2 @@ -25,7 +25,7 @@ from google.iam.v1 import iam_policy_pb2 as iam_policy # type: ignore from google.iam.v1 import policy_pb2 as policy # type: ignore {% endif %} {% endfilter %} -from .transports.base import {{ service.name }}Transport +from .transports.base import {{ service.name }}Transport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import {{ service.grpc_asyncio_transport_name }} from .client import {{ service.client_name }} @@ -52,6 +52,7 @@ class {{ service.async_client_name }}: credentials: credentials.Credentials = None, transport: Union[str, {{ service.name }}Transport] = 'grpc_asyncio', client_options: ClientOptions = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the {{ (service.client_name|snake_case).replace('_', ' ') }}. @@ -87,6 +88,8 @@ class {{ service.async_client_name }}: credentials=credentials, transport=transport, client_options=client_options, + client_info=client_info, + ) {% for method in service.methods.values() -%} @@ -202,7 +205,7 @@ class {{ service.async_client_name }}: ), {%- endif %} default_timeout={{ method.timeout }}, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) {%- if method.field_headers %} @@ -352,7 +355,7 @@ class {{ service.async_client_name }}: rpc = gapic_v1.method_async.wrap_method( self._client._transport.set_iam_policy, default_timeout=None, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -459,7 +462,7 @@ class {{ service.async_client_name }}: rpc = gapic_v1.method_async.wrap_method( self._client._transport.get_iam_policy, default_timeout=None, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -510,7 +513,7 @@ class {{ service.async_client_name }}: rpc = gapic_v1.method_async.wrap_method( self._client._transport.test_iam_permissions, default_timeout=None, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -527,13 +530,13 @@ class {{ service.async_client_name }}: {% endif %} try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( '{{ api.naming.warehouse_package_name }}', ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ( diff --git a/gapic/templates/%namespace/%name_%version/%sub/services/%service/client.py.j2 b/gapic/templates/%namespace/%name_%version/%sub/services/%service/client.py.j2 index 9f4ba15908..0aef4812bc 100644 --- a/gapic/templates/%namespace/%name_%version/%sub/services/%service/client.py.j2 +++ b/gapic/templates/%namespace/%name_%version/%sub/services/%service/client.py.j2 @@ -27,7 +27,7 @@ from google.iam.v1 import iam_policy_pb2 as iam_policy # type: ignore from google.iam.v1 import policy_pb2 as policy # type: ignore {% endif %} {% endfilter %} -from .transports.base import {{ service.name }}Transport +from .transports.base import {{ service.name }}Transport, DEFAULT_CLIENT_INFO from .transports.grpc import {{ service.grpc_transport_name }} from .transports.grpc_asyncio import {{ service.grpc_asyncio_transport_name }} @@ -141,6 +141,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta): credentials: credentials.Credentials = None, transport: Union[str, {{ service.name }}Transport] = None, client_options: ClientOptions = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the {{ (service.client_name|snake_case).replace('_', ' ') }}. @@ -166,7 +167,12 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta): (2) The ``client_cert_source`` property is used to provide client SSL credentials for mutual TLS transport. If not provided, the default SSL credentials will be used if present. - + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + 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 client library. + Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport creation failed for any reason. @@ -219,6 +225,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta): api_mtls_endpoint=client_options.api_endpoint, client_cert_source=client_options.client_cert_source, quota_project_id=client_options.quota_project_id, + client_info=client_info, ) @@ -471,7 +478,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta): rpc = gapic_v1.method.wrap_method( self._transport.set_iam_policy, default_timeout=None, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -578,7 +585,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta): rpc = gapic_v1.method.wrap_method( self._transport.get_iam_policy, default_timeout=None, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -629,7 +636,7 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta): rpc = gapic_v1.method.wrap_method( self._transport.test_iam_permissions, default_timeout=None, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -647,13 +654,13 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta): try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( '{{ api.naming.warehouse_package_name }}', ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ( diff --git a/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/base.py.j2 b/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/base.py.j2 index dbc64639d7..3ee35f8724 100644 --- a/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/base.py.j2 +++ b/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/base.py.j2 @@ -26,13 +26,13 @@ from google.iam.v1 import policy_pb2 as policy # type: ignore {% endfilter %} try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( '{{ api.naming.warehouse_package_name }}', ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() class {{ service.name }}Transport(abc.ABC): """Abstract transport class for {{ service.name }}.""" @@ -50,6 +50,7 @@ class {{ service.name }}Transport(abc.ABC): credentials_file: typing.Optional[str] = None, scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, quota_project_id: typing.Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, **kwargs, ) -> None: """Instantiate the transport. @@ -68,6 +69,11 @@ class {{ service.name }}Transport(abc.ABC): scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + 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 client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ':' not in host: @@ -93,10 +99,10 @@ class {{ service.name }}Transport(abc.ABC): self._credentials = credentials # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages() + self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self): + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { {% for method in service.methods.values() -%} @@ -117,7 +123,7 @@ class {{ service.name }}Transport(abc.ABC): ), {%- endif %} default_timeout={{ method.timeout }}, - client_info=_client_info, + client_info=client_info, ), {% endfor %} {# precomputed wrappers loop #} } diff --git a/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/grpc.py.j2 b/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/grpc.py.j2 index f4a81c31f1..0952a1a7ca 100644 --- a/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/grpc.py.j2 +++ b/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/grpc.py.j2 @@ -7,6 +7,7 @@ from google.api_core import grpc_helpers # type: ignore {%- if service.has_lro %} from google.api_core import operations_v1 # type: ignore {%- endif %} +from google.api_core import gapic_v1 # type: ignore from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -24,7 +25,7 @@ from google.iam.v1 import iam_policy_pb2 as iam_policy # type: ignore from google.iam.v1 import policy_pb2 as policy # type: ignore {% endif %} {% endfilter %} -from .base import {{ service.name }}Transport +from .base import {{ service.name }}Transport, DEFAULT_CLIENT_INFO class {{ service.name }}GrpcTransport({{ service.name }}Transport): @@ -49,7 +50,9 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport): channel: grpc.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, - quota_project_id: Optional[str] = None) -> None: + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: """Instantiate the transport. Args: @@ -78,6 +81,11 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport): is None. quota_project_id (Optional[str]): An optional project to use for billing and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + 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 client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -127,6 +135,7 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport): credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) @classmethod diff --git a/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/grpc_asyncio.py.j2 b/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/grpc_asyncio.py.j2 index dbf71b2962..7015b31cfb 100644 --- a/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/grpc_asyncio.py.j2 +++ b/gapic/templates/%namespace/%name_%version/%sub/services/%service/transports/grpc_asyncio.py.j2 @@ -3,6 +3,7 @@ {% block content %} from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple +from google.api_core import gapic_v1 # type: ignore from google.api_core import grpc_helpers_async # type: ignore {%- if service.has_lro %} from google.api_core import operations_v1 # type: ignore @@ -23,7 +24,7 @@ from google.iam.v1 import iam_policy_pb2 as iam_policy # type: ignore from google.iam.v1 import policy_pb2 as policy # type: ignore {% endif %} {% endfilter %} -from .base import {{ service.name }}Transport +from .base import {{ service.name }}Transport, DEFAULT_CLIENT_INFO from .grpc import {{ service.name }}GrpcTransport @@ -91,6 +92,7 @@ class {{ service.grpc_asyncio_transport_name }}({{ service.name }}Transport): api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -121,6 +123,11 @@ class {{ service.grpc_asyncio_transport_name }}({{ service.name }}Transport): is None. quota_project_id (Optional[str]): An optional project to use for billing and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + 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 client library. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -165,6 +172,7 @@ class {{ service.grpc_asyncio_transport_name }}({{ service.name }}Transport): credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) self._stubs = {} diff --git a/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2 b/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2 index 2fc3923b2a..ff14d7766d 100644 --- a/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2 +++ b/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2 @@ -28,9 +28,7 @@ from google.api_core import future from google.api_core import operations_v1 from google.longrunning import operations_pb2 {% endif -%} -{% if service.has_pagers -%} from google.api_core import gapic_v1 -{% endif -%} {% for method in service.methods.values() -%} {% for ref_type in method.ref_types if not ((ref_type.ident.python_import.package == ('google', 'api_core') and ref_type.ident.python_import.module == 'operation') @@ -127,6 +125,7 @@ def test_{{ service.client_name|snake_case }}_client_options(client_class, trans api_mtls_endpoint="squid.clam.whelk", client_cert_source=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is @@ -143,6 +142,7 @@ def test_{{ service.client_name|snake_case }}_client_options(client_class, trans api_mtls_endpoint=client.DEFAULT_ENDPOINT, client_cert_source=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is @@ -159,6 +159,7 @@ def test_{{ service.client_name|snake_case }}_client_options(client_class, trans api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, client_cert_source=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is @@ -176,7 +177,7 @@ def test_{{ service.client_name|snake_case }}_client_options(client_class, trans api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, client_cert_source=client_cert_source_callback, quota_project_id=None, - + client_info=transports.base.DEFAULT_CLIENT_INFO, ) # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is @@ -194,6 +195,7 @@ def test_{{ service.client_name|snake_case }}_client_options(client_class, trans api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, client_cert_source=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is @@ -211,6 +213,7 @@ def test_{{ service.client_name|snake_case }}_client_options(client_class, trans api_mtls_endpoint=client.DEFAULT_ENDPOINT, client_cert_source=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS has @@ -232,6 +235,7 @@ def test_{{ service.client_name|snake_case }}_client_options(client_class, trans api_mtls_endpoint=client.DEFAULT_ENDPOINT, client_cert_source=None, quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -255,6 +259,7 @@ def test_{{ service.client_name|snake_case }}_client_options_scopes(client_class api_mtls_endpoint=client.DEFAULT_ENDPOINT, client_cert_source=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -278,6 +283,7 @@ def test_{{ service.client_name|snake_case }}_client_options_credentials_file(cl api_mtls_endpoint=client.DEFAULT_ENDPOINT, client_cert_source=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -295,6 +301,7 @@ def test_{{ service.client_name|snake_case }}_client_options_from_dict(): api_mtls_endpoint="squid.clam.whelk", client_cert_source=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -1362,6 +1369,26 @@ def test_parse_{{ message.resource_type|snake_case }}_path(): {% endwith -%} {% endfor -%} + +def test_client_withDEFAULT_CLIENT_INFO(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object(transports.{{ service.name }}Transport, '_prep_wrapped_messages') as prep: + client = {{ service.client_name }}( + credentials=credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object(transports.{{ service.name }}Transport, '_prep_wrapped_messages') as prep: + transport_class = {{ service.client_name }}.get_transport_class() + transport = transport_class( + credentials=credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + {% if opts.add_iam_methods %} def test_set_iam_policy(transport: str = "grpc"): client = {{ service.client_name }}(