Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: strip trailing _ from field mask paths #228

Merged
merged 1 commit into from Aug 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions google/api_core/protobuf_helpers.py
Expand Up @@ -357,6 +357,13 @@ def _field_mask_helper(original, modified, current=""):


def _get_path(current, name):
# 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.
# APIs will reject field masks if fields have trailing underscores.
# See https://github.com/googleapis/python-api-core/issues/227
name = name.rstrip("_")
if not current:
return name
return "%s.%s" % (current, name)
Expand Down
5 changes: 3 additions & 2 deletions noxfile.py
Expand Up @@ -98,9 +98,10 @@ def default(session):
]
pytest_args.extend(session.posargs)

# Inject AsyncIO content, if version >= 3.6.
# Inject AsyncIO content and proto-plus, if version >= 3.6.
# proto-plus is needed for a field mask test in test_protobuf_helpers.py
if _greater_or_equal_than_36(session.python):
session.install("asyncmock", "pytest-asyncio")
session.install("asyncmock", "pytest-asyncio", "proto-plus")

pytest_args.append("--cov=tests.asyncio")
pytest_args.append(os.path.join("tests", "asyncio"))
Expand Down
44 changes: 44 additions & 0 deletions tests/unit/test_protobuf_helpers.py
Expand Up @@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import sys

import pytest

from google.api import http_pb2
Expand Down Expand Up @@ -472,3 +474,45 @@ def test_field_mask_different_level_diffs():
"alpha",
"red",
]


@pytest.mark.skipif(
sys.version_info.major == 2,
reason="Field names with trailing underscores can only be created"
"through proto-plus, which is Python 3 only.",
)
def test_field_mask_ignore_trailing_underscore():
import proto

class Foo(proto.Message):
type_ = proto.Field(proto.STRING, number=1)
input_config = proto.Field(proto.STRING, number=2)

modified = Foo(type_="bar", input_config="baz")

assert sorted(protobuf_helpers.field_mask(None, Foo.pb(modified)).paths) == [
"input_config",
"type",
]


@pytest.mark.skipif(
sys.version_info.major == 2,
reason="Field names with trailing underscores can only be created"
"through proto-plus, which is Python 3 only.",
)
def test_field_mask_ignore_trailing_underscore_with_nesting():
import proto

class Bar(proto.Message):
class Baz(proto.Message):
input_config = proto.Field(proto.STRING, number=1)

type_ = proto.Field(Baz, number=1)

modified = Bar()
modified.type_.input_config = "foo"

assert sorted(protobuf_helpers.field_mask(None, Bar.pb(modified)).paths) == [
"type.input_config",
]