Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
24 changes: 22 additions & 2 deletions google/api_core/path_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,26 @@ def transcode(http_options, message=None, **request_kwargs):
# Assign body and query params
body = http_option.get("body")

# gapic-generator-python appends an underscore to field names
# that collide with python keywords. See related issue
# https://github.com/googleapis/python-api-core/issues/227
# Make sure that when the fields are REST encoded, the
# Python-specific trailing underscore is removed before going on the wire.
# `leftovers` can either be a dict or protobuf message.
# When `leftovers` is a dict, the `_` suffix in each key
# is stripped away as it is not possible to natively define a field
# with a trailing underscore in protobuf.
# When `leftovers` is a protobuf message, we need to use an underscore
# suffix when accessing the field in the protobuf message when the
# field has an underscore suffix.
field_suffix = ""

if isinstance(leftovers, dict):
leftovers = {key.rstrip("_"): val for key, val in leftovers.items()}
elif body:
if hasattr(leftovers, body + "_"):
field_suffix = "_"

if body:
if body == "*":
request["body"] = leftovers
Expand All @@ -308,8 +328,8 @@ def transcode(http_options, message=None, **request_kwargs):
else:
try:
if message:
request["body"] = getattr(leftovers, body)
delete_field(leftovers, body)
request["body"] = getattr(leftovers, f"{body}{field_suffix}")
delete_field(leftovers, f"{body}{field_suffix}")
else:
request["body"] = leftovers.pop(body)
except (KeyError, AttributeError):
Expand Down
33 changes: 33 additions & 0 deletions tests/unit/test_path_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,22 @@
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)
stacktrace_ = proto.Field(proto.STRING, number=3)


@pytest.mark.parametrize(
"tmpl, args, kwargs, expected_result",
[
Expand Down Expand Up @@ -413,6 +425,27 @@ 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="foo"), debuggee_id="bar", stacktrace_="baz"
)._pb,
{},
[
"post",
"/v1/no/template",
Breakpoint(name="foo")._pb,
SomeMessage(debuggee_id="bar", stacktrace_="baz")._pb,
],
],
[
[["post", "/v1/no/template", "oauth"]],
auth_pb2.AuthenticationRule(
Expand Down