Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -179,20 +179,34 @@ class {{ service.name }}Transport(abc.ABC):
stripped for backward compatibility with older `google-api-core`
versions.
"""
if _WRAP_METHOD_SUPPORTS_TRACING: # pragma: NO COVER

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We added tests to remove the crutch of relying on pragmas.

if _WRAP_METHOD_SUPPORTS_TRACING:
kwargs["client_options"] = self._client_options
try:
kind = self.kind
except NotImplementedError: # pragma: NO COVER
except NotImplementedError:
kind = None
if kind: # pragma: NO COVER
if kind:
kwargs["kind"] = kind
return gapic_v1.method.wrap_method(func, *args, **kwargs)
# The fallback below strips tracing-specific arguments when an older version
# of google-api-core is installed (which does not accept client_options, etc.).
for k in ["client_options", "method_name", "is_streaming", "kind"]: # pragma: NO COVER
kwargs.pop(k, None) # pragma: NO COVER
return gapic_v1.method.wrap_method(func, *args, **kwargs) # pragma: NO COVER
# Fallback for older runtime versions of google-api-core:
# - Era 1 (< 2.29.0): Neither tracing args nor `kind` are supported.
# - Era 2 (>= 2.29.0, < 2.36.0): `kind` is supported (prevents REST from
# falling back to gRPC wrapping), but tracing args are not.
# (These fallbacks can be removed once google-api-core < 2.36.0 is no longer supported.)
for k in ["client_options", "method_name", "is_streaming"]:
kwargs.pop(k, None)

try:
kind = self.kind
except NotImplementedError:
kind = None

if _WRAP_METHOD_SUPPORTS_KIND and kind:
kwargs["kind"] = kind
else:
kwargs.pop("kind", None)

return gapic_v1.method.wrap_method(func, *args, **kwargs)

def _wrap_async_method(self, func, *args, **kwargs):
"""Wrap an async RPC method with common client-level features.
Expand All @@ -204,20 +218,34 @@ class {{ service.name }}Transport(abc.ABC):
stripped for backward compatibility with older `google-api-core`
versions.
"""
if _ASYNC_WRAP_METHOD_SUPPORTS_TRACING: # pragma: NO COVER
if _ASYNC_WRAP_METHOD_SUPPORTS_TRACING:
kwargs["client_options"] = self._client_options
try:
kind = self.kind
except NotImplementedError: # pragma: NO COVER
except NotImplementedError:
kind = None
if kind: # pragma: NO COVER
if kind:
kwargs["kind"] = kind
return gapic_v1.method_async.wrap_method(func, *args, **kwargs)
# The fallback below strips tracing-specific arguments when an older version
# of google-api-core is installed (which does not accept client_options, etc.).
for k in ["client_options", "method_name", "is_streaming", "kind"]: # pragma: NO COVER
kwargs.pop(k, None) # pragma: NO COVER
return gapic_v1.method_async.wrap_method(func, *args, **kwargs) # pragma: NO COVER
# Fallback for older runtime versions of google-api-core:
# - Era 1 (< 2.29.0): Neither tracing args nor `kind` are supported.
# - Era 2 (>= 2.29.0, < 2.36.0): `kind` is supported (prevents REST from
# falling back to gRPC wrapping), but tracing args are not.
# (These fallbacks can be removed once google-api-core < 2.36.0 is no longer supported.)
for k in ["client_options", "method_name", "is_streaming"]:
kwargs.pop(k, None)

try:
kind = self.kind
except NotImplementedError:
kind = None

if _ASYNC_WRAP_METHOD_SUPPORTS_KIND and kind:
kwargs["kind"] = kind
else:
kwargs.pop("kind", None)

return gapic_v1.method_async.wrap_method(func, *args, **kwargs)

def _prep_wrapped_messages(self, client_info):
"""Precompute and cache wrapped methods for RPC dispatch."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ class {{ service.name }}GrpcTransport({{ service.name }}Transport):
credentials=transport._credentials,
client_info=transport._client_info,
client_cert_source_for_mtls=transport._client_cert_source_for_mtls,
client_options=getattr(transport, "_client_options", None),
)
return transport._rest_transport.{{ method.transport_safe_name|snake_case }}(*args, **kwargs)
self._stubs['{{ method.transport_safe_name|snake_case }}'] = _RestStub()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ class {{ service.grpc_asyncio_transport_name }}({{ service.name }}Transport):
host=transport._host,
credentials=transport._credentials,
client_info=transport._client_info,
client_options=getattr(transport, "_client_options", None),
)
return transport._rest_transport.{{ method.transport_safe_name|snake_case }}(*args, **kwargs)
self._stubs['{{ method.transport_safe_name|snake_case }}'] = _AsyncRestStub()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1817,6 +1817,7 @@ async def test_{{ service.name|snake_case }}_{{ method.name|snake_case }}_grpc_a
host=transport._host,
credentials=transport._credentials,
client_info=transport._client_info,
client_options=getattr(transport, "_client_options", None),
)
assert mock_rest_transport.{{ method.transport_safe_name|snake_case }}.call_count == 2
await transport.close()
Expand Down Expand Up @@ -2475,4 +2476,200 @@ def test_api_key_credentials(client_class, transport_class):
api_audience=None,
)


def test_{{ service.name|snake_case }}_base_transport_wrap_method_modern_api_core(monkeypatch):
monkeypatch.setattr(transports.base, "_WRAP_METHOD_SUPPORTS_TRACING", True)
# 1. Concrete transport: passes client_options=None and kind="{{ opts.transport[0] }}"
with mock.patch.object(transports.base.gapic_v1.method, "wrap_method") as mock_wrap:
transport = transports.{{ service.name }}{{ opts.transport[0].capitalize() }}Transport(
credentials=ga_credentials.AnonymousCredentials()
)
func = mock.MagicMock()
transport._wrap_method(func)
assert mock_wrap.call_args.kwargs["kind"] == "{{ opts.transport[0] }}"
assert "client_options" in mock_wrap.call_args.kwargs

# 2. Base transport: kind raises NotImplementedError and is cleanly omitted
with mock.patch.object(transports.base.gapic_v1.method, "wrap_method") as mock_wrap:
base_transport = transports.{{ service.name }}Transport(
credentials=ga_credentials.AnonymousCredentials()
)
func = mock.MagicMock()
base_transport._wrap_method(func)
assert "kind" not in mock_wrap.call_args.kwargs
assert "client_options" in mock_wrap.call_args.kwargs


def test_{{ service.name|snake_case }}_base_transport_wrap_method_older_api_core_fallbacks(monkeypatch):
monkeypatch.setattr(transports.base, "_WRAP_METHOD_SUPPORTS_TRACING", False)
with mock.patch.object(transports.base.gapic_v1.method, "wrap_method"):
transport = transports.{{ service.name }}{{ opts.transport[0].capitalize() }}Transport(
credentials=ga_credentials.AnonymousCredentials()
)

# Era 1: Ancient google-api-core (< 2.29.0: can be removed once google-api-core < 2.29.0 is no longer supported)
monkeypatch.setattr(transports.base, "_WRAP_METHOD_SUPPORTS_KIND", False)
with mock.patch.object(transports.base.gapic_v1.method, "wrap_method") as mock_wrap:
func = mock.MagicMock()
transport._wrap_method(
func,
client_options="fake_options",
method_name="fake_method",
is_streaming=False,
)
kwargs = mock_wrap.call_args.kwargs
assert "kind" not in kwargs
assert "client_options" not in kwargs
assert "method_name" not in kwargs
assert "is_streaming" not in kwargs

with mock.patch.object(transports.base.gapic_v1.method, "wrap_method") as mock_wrap:
base_transport = transports.{{ service.name }}Transport(
credentials=ga_credentials.AnonymousCredentials()
)
func = mock.MagicMock()
base_transport._wrap_method(
func,
client_options="fake_options",
method_name="fake_method",
is_streaming=False,
)
kwargs = mock_wrap.call_args.kwargs
assert "kind" not in kwargs
assert "client_options" not in kwargs
assert "method_name" not in kwargs
assert "is_streaming" not in kwargs

# Era 2: Intermediate google-api-core (>= 2.29.0, < 2.36.0: can be removed once google-api-core < 2.36.0 is no longer supported)
monkeypatch.setattr(transports.base, "_WRAP_METHOD_SUPPORTS_KIND", True)
with mock.patch.object(transports.base.gapic_v1.method, "wrap_method") as mock_wrap:
func = mock.MagicMock()
transport._wrap_method(
func,
client_options="fake_options",
method_name="fake_method",
is_streaming=False,
)
kwargs = mock_wrap.call_args.kwargs
assert kwargs.get("kind") == "{{ opts.transport[0] }}"
assert "client_options" not in kwargs
assert "method_name" not in kwargs
assert "is_streaming" not in kwargs

with mock.patch.object(transports.base.gapic_v1.method, "wrap_method") as mock_wrap:
base_transport = transports.{{ service.name }}Transport(
credentials=ga_credentials.AnonymousCredentials()
)
func = mock.MagicMock()
base_transport._wrap_method(
func,
client_options="fake_options",
method_name="fake_method",
is_streaming=False,
)
kwargs = mock_wrap.call_args.kwargs
assert "kind" not in kwargs
assert "client_options" not in kwargs
assert "method_name" not in kwargs
assert "is_streaming" not in kwargs


{% if 'grpc' in opts.transport %}
def test_{{ service.name|snake_case }}_base_transport_wrap_async_method_modern_api_core(monkeypatch):
monkeypatch.setattr(transports.base, "_ASYNC_WRAP_METHOD_SUPPORTS_TRACING", True)
# 1. Concrete transport: passes client_options=None and kind="grpc_asyncio"
with mock.patch.object(transports.base.gapic_v1.method_async, "wrap_method") as mock_wrap:
transport = transports.{{ service.grpc_asyncio_transport_name }}(
credentials=ga_credentials.AnonymousCredentials()
)
func = mock.MagicMock()
transport._wrap_async_method(func)
assert mock_wrap.call_args.kwargs["kind"] == "grpc_asyncio"
assert "client_options" in mock_wrap.call_args.kwargs

# 2. Base transport: kind raises NotImplementedError and is cleanly omitted
with mock.patch.object(transports.base.gapic_v1.method_async, "wrap_method") as mock_wrap:
base_transport = transports.{{ service.name }}Transport(
credentials=ga_credentials.AnonymousCredentials()
)
func = mock.MagicMock()
base_transport._wrap_async_method(func)
assert "kind" not in mock_wrap.call_args.kwargs
assert "client_options" in mock_wrap.call_args.kwargs


def test_{{ service.name|snake_case }}_base_transport_wrap_async_method_older_api_core_fallbacks(monkeypatch):
monkeypatch.setattr(transports.base, "_ASYNC_WRAP_METHOD_SUPPORTS_TRACING", False)
with mock.patch.object(transports.base.gapic_v1.method_async, "wrap_method"):
transport = transports.{{ service.grpc_asyncio_transport_name }}(
credentials=ga_credentials.AnonymousCredentials()
)

# Era 1: Ancient google-api-core (< 2.29.0: can be removed once google-api-core < 2.29.0 is no longer supported)
monkeypatch.setattr(transports.base, "_ASYNC_WRAP_METHOD_SUPPORTS_KIND", False)
with mock.patch.object(transports.base.gapic_v1.method_async, "wrap_method") as mock_wrap:
func = mock.MagicMock()
transport._wrap_async_method(
func,
client_options="fake_options",
method_name="fake_method",
is_streaming=False,
)
kwargs = mock_wrap.call_args.kwargs
assert "kind" not in kwargs
assert "client_options" not in kwargs
assert "method_name" not in kwargs
assert "is_streaming" not in kwargs

with mock.patch.object(transports.base.gapic_v1.method_async, "wrap_method") as mock_wrap:
base_transport = transports.{{ service.name }}Transport(
credentials=ga_credentials.AnonymousCredentials()
)
func = mock.MagicMock()
base_transport._wrap_async_method(
func,
client_options="fake_options",
method_name="fake_method",
is_streaming=False,
)
kwargs = mock_wrap.call_args.kwargs
assert "kind" not in kwargs
assert "client_options" not in kwargs
assert "method_name" not in kwargs
assert "is_streaming" not in kwargs

# Era 2: Intermediate google-api-core (>= 2.29.0, < 2.36.0: can be removed once google-api-core < 2.36.0 is no longer supported)
monkeypatch.setattr(transports.base, "_ASYNC_WRAP_METHOD_SUPPORTS_KIND", True)
with mock.patch.object(transports.base.gapic_v1.method_async, "wrap_method") as mock_wrap:
func = mock.MagicMock()
transport._wrap_async_method(
func,
client_options="fake_options",
method_name="fake_method",
is_streaming=False,
)
kwargs = mock_wrap.call_args.kwargs
assert kwargs.get("kind") == "grpc_asyncio"
assert "client_options" not in kwargs
assert "method_name" not in kwargs
assert "is_streaming" not in kwargs

with mock.patch.object(transports.base.gapic_v1.method_async, "wrap_method") as mock_wrap:
base_transport = transports.{{ service.name }}Transport(
credentials=ga_credentials.AnonymousCredentials()
)
func = mock.MagicMock()
base_transport._wrap_async_method(
func,
client_options="fake_options",
method_name="fake_method",
is_streaming=False,
)
kwargs = mock_wrap.call_args.kwargs
assert "kind" not in kwargs
assert "client_options" not in kwargs
assert "method_name" not in kwargs
assert "is_streaming" not in kwargs
{% endif %}

{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -150,20 +150,34 @@ def _wrap_method(self, func, *args, **kwargs):
stripped for backward compatibility with older `google-api-core`
versions.
"""
if _WRAP_METHOD_SUPPORTS_TRACING: # pragma: NO COVER
if _WRAP_METHOD_SUPPORTS_TRACING:
kwargs["client_options"] = self._client_options
try:
kind = self.kind
except NotImplementedError: # pragma: NO COVER
except NotImplementedError:
kind = None
if kind: # pragma: NO COVER
if kind:
kwargs["kind"] = kind
return gapic_v1.method.wrap_method(func, *args, **kwargs)
# The fallback below strips tracing-specific arguments when an older version
# of google-api-core is installed (which does not accept client_options, etc.).
for k in ["client_options", "method_name", "is_streaming", "kind"]: # pragma: NO COVER
kwargs.pop(k, None) # pragma: NO COVER
return gapic_v1.method.wrap_method(func, *args, **kwargs) # pragma: NO COVER
# Fallback for older runtime versions of google-api-core:
# - Era 1 (< 2.29.0): Neither tracing args nor `kind` are supported.
# - Era 2 (>= 2.29.0, < 2.36.0): `kind` is supported (prevents REST from
# falling back to gRPC wrapping), but tracing args are not.
# (These fallbacks can be removed once google-api-core < 2.36.0 is no longer supported.)
for k in ["client_options", "method_name", "is_streaming"]:
kwargs.pop(k, None)

try:
kind = self.kind
except NotImplementedError:
kind = None

if _WRAP_METHOD_SUPPORTS_KIND and kind:
kwargs["kind"] = kind
else:
kwargs.pop("kind", None)

return gapic_v1.method.wrap_method(func, *args, **kwargs)

def _wrap_async_method(self, func, *args, **kwargs):
"""Wrap an async RPC method with common client-level features.
Expand All @@ -175,20 +189,34 @@ def _wrap_async_method(self, func, *args, **kwargs):
stripped for backward compatibility with older `google-api-core`
versions.
"""
if _ASYNC_WRAP_METHOD_SUPPORTS_TRACING: # pragma: NO COVER
if _ASYNC_WRAP_METHOD_SUPPORTS_TRACING:
kwargs["client_options"] = self._client_options
try:
kind = self.kind
except NotImplementedError: # pragma: NO COVER
except NotImplementedError:
kind = None
if kind: # pragma: NO COVER
if kind:
kwargs["kind"] = kind
return gapic_v1.method_async.wrap_method(func, *args, **kwargs)
# The fallback below strips tracing-specific arguments when an older version
# of google-api-core is installed (which does not accept client_options, etc.).
for k in ["client_options", "method_name", "is_streaming", "kind"]: # pragma: NO COVER
kwargs.pop(k, None) # pragma: NO COVER
return gapic_v1.method_async.wrap_method(func, *args, **kwargs) # pragma: NO COVER
# Fallback for older runtime versions of google-api-core:
# - Era 1 (< 2.29.0): Neither tracing args nor `kind` are supported.
# - Era 2 (>= 2.29.0, < 2.36.0): `kind` is supported (prevents REST from
# falling back to gRPC wrapping), but tracing args are not.
# (These fallbacks can be removed once google-api-core < 2.36.0 is no longer supported.)
for k in ["client_options", "method_name", "is_streaming"]:
kwargs.pop(k, None)

try:
kind = self.kind
except NotImplementedError:
kind = None

if _ASYNC_WRAP_METHOD_SUPPORTS_KIND and kind:
kwargs["kind"] = kind
else:
kwargs.pop("kind", None)

return gapic_v1.method_async.wrap_method(func, *args, **kwargs)

def _prep_wrapped_messages(self, client_info):
"""Precompute and cache wrapped methods for RPC dispatch."""
Expand Down
Loading
Loading