Skip to content

Commit ccce0fe

Browse files
authored
fix: strip trailing _ from field mask paths (#228) (#251)
1 parent 6af450b commit ccce0fe

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

google/api_core/protobuf_helpers.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,13 @@ def _field_mask_helper(original, modified, current=""):
357357

358358

359359
def _get_path(current, name):
360+
# gapic-generator-python appends underscores to field names
361+
# that collide with python keywords.
362+
# `_` is stripped away as it is not possible to
363+
# natively define a field with a trailing underscore in protobuf.
364+
# APIs will reject field masks if fields have trailing underscores.
365+
# See https://github.com/googleapis/python-api-core/issues/227
366+
name = name.rstrip("_")
360367
if not current:
361368
return name
362369
return "%s.%s" % (current, name)

noxfile.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,10 @@ def default(session):
9898
]
9999
pytest_args.extend(session.posargs)
100100

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

105106
pytest_args.append("--cov=tests.asyncio")
106107
pytest_args.append(os.path.join("tests", "asyncio"))

tests/unit/test_protobuf_helpers.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import sys
16+
1517
import pytest
1618

1719
from google.api import http_pb2
@@ -472,3 +474,45 @@ def test_field_mask_different_level_diffs():
472474
"alpha",
473475
"red",
474476
]
477+
478+
479+
@pytest.mark.skipif(
480+
sys.version_info.major == 2,
481+
reason="Field names with trailing underscores can only be created"
482+
"through proto-plus, which is Python 3 only.",
483+
)
484+
def test_field_mask_ignore_trailing_underscore():
485+
import proto
486+
487+
class Foo(proto.Message):
488+
type_ = proto.Field(proto.STRING, number=1)
489+
input_config = proto.Field(proto.STRING, number=2)
490+
491+
modified = Foo(type_="bar", input_config="baz")
492+
493+
assert sorted(protobuf_helpers.field_mask(None, Foo.pb(modified)).paths) == [
494+
"input_config",
495+
"type",
496+
]
497+
498+
499+
@pytest.mark.skipif(
500+
sys.version_info.major == 2,
501+
reason="Field names with trailing underscores can only be created"
502+
"through proto-plus, which is Python 3 only.",
503+
)
504+
def test_field_mask_ignore_trailing_underscore_with_nesting():
505+
import proto
506+
507+
class Bar(proto.Message):
508+
class Baz(proto.Message):
509+
input_config = proto.Field(proto.STRING, number=1)
510+
511+
type_ = proto.Field(Baz, number=1)
512+
513+
modified = Bar()
514+
modified.type_.input_config = "foo"
515+
516+
assert sorted(protobuf_helpers.field_mask(None, Bar.pb(modified)).paths) == [
517+
"type.input_config",
518+
]

0 commit comments

Comments
 (0)