Skip to content
This repository was archived by the owner on Feb 23, 2026. It is now read-only.
Closed
22 changes: 20 additions & 2 deletions google/api_core/path_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,27 @@ def transcode(http_options, message=None, **request_kwargs):
else:
try:
if message:
request["body"] = getattr(leftovers, body)
delete_field(leftovers, body)
try:
request["body"] = getattr(leftovers, body)
delete_field(leftovers, body)
except AttributeError as e:
# gapic-generator-python appends underscores to field names
# that collide with python keywords.
# `_` is stripped away as it is not possible to
# natively define a field with a trailing underscore in protobuf.
# See related issue
# https://github.com/googleapis/python-api-core/issues/227
if hasattr(leftovers, body + "_"):
Comment thread
parthea marked this conversation as resolved.
Outdated
request["body"] = getattr(leftovers, body + "_")
delete_field(leftovers, body + "_")
else:
raise e
else:
Comment thread
parthea marked this conversation as resolved.
# gapic-generator-python appends underscores to field names
# that collide with python keywords.
leftovers = {
key.rstrip("_"): val for key, val in leftovers.items()
}
request["body"] = leftovers.pop(body)
except (KeyError, AttributeError):
continue
Expand Down
30 changes: 30 additions & 0 deletions tests/unit/test_path_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,21 @@
import mock
import pytest

import proto

from google.api import auth_pb2
from google.api_core import path_template


class Breakpoint(proto.Message):
name = proto.Field(proto.STRING, number=1)


class SomeMessage(proto.Message):
breakpoint_ = proto.Field(Breakpoint, number=1)
debuggee_id = proto.Field(proto.STRING, number=2)


@pytest.mark.parametrize(
"tmpl, args, kwargs, expected_result",
[
Expand Down Expand Up @@ -413,6 +424,25 @@ def test_transcode_with_wildcard(
{"data": {"id": 1, "info": "some info"}, "foo": "bar"},
["post", "/v1/no/template", {"id": 1, "info": "some info"}, {"foo": "bar"}],
],
# Single field body with trailing underscore
[
[["post", "/v1/no/template", "data"]],
None,
{"data": {"id": 1, "info": "some info"}, "foo_": "bar"},
["post", "/v1/no/template", {"id": 1, "info": "some info"}, {"foo": "bar"}],
],
# Single field body with reserved keyword, using message where field name has trailing underscore
[
[["post", "/v1/no/template", "breakpoint"]],
SomeMessage(breakpoint_=Breakpoint(name="test"), debuggee_id="test")._pb,
Comment thread
parthea marked this conversation as resolved.
Outdated
{},
[
"post",
"/v1/no/template",
Breakpoint(name="test")._pb,
SomeMessage(debuggee_id="test")._pb,
],
],
[
[["post", "/v1/no/template", "oauth"]],
auth_pb2.AuthenticationRule(
Expand Down