Skip to content
This repository was archived by the owner on Mar 26, 2026. It is now read-only.
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions gapic/schema/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,16 @@ def mock_value(self) -> str:
sub = next(iter(self.type.fields.values()))
answer = f'{self.type.ident}({sub.name}={sub.mock_value})'

# If this is a repeated field, then the mock answer should
# be a list.
if self.repeated:
if self.map:
# Maps are a special case beacuse they're represented internally as
# a list of a generated type with two fields: 'key' and 'value'.
answer = '{{{}: {}}}'.format(
self.type.fields["key"].mock_value,
self.type.fields["value"].mock_value,
)
elif self.repeated:
# If this is a repeated field, then the mock answer should
# be a list.
answer = f'[{answer}]'

# Done; return the mock value.
Expand Down Expand Up @@ -568,7 +575,6 @@ def field_headers(self) -> Sequence[str]:
@utils.cached_property
def flattened_fields(self) -> Mapping[str, Field]:
"""Return the signature defined for this method."""
signatures = self.options.Extensions[client_pb2.method_signature]
cross_pkg_request = self.input.ident.package != self.ident.package

def filter_fields(sig):
Expand All @@ -585,6 +591,7 @@ def filter_fields(sig):

yield name, field

signatures = self.options.Extensions[client_pb2.method_signature]
answer: Dict[str, Field] = collections.OrderedDict(
name_and_field
for sig in signatures
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,11 @@ class {{ service.client_name }}(metaclass={{ service.client_name }}Meta):
{% endif %} {# different request package #}

{#- Vanilla python protobuf wrapper types cannot _set_ repeated fields #}
{%- for key, field in method.flattened_fields.items() if not(field.repeated and method.input.ident.package != method.ident.package) %}
{% if method.flattened_fields -%}
# If we have keyword arguments corresponding to fields on the
# request, apply these.
{% endif -%}
{%- for key, field in method.flattened_fields.items() if not(field.repeated and method.input.ident.package != method.ident.package) %}
if {{ field.name }} is not None:
request.{{ key }} = {{ field.name }}
{%- endfor %}
Expand Down
43 changes: 42 additions & 1 deletion tests/unit/schema/wrappers/test_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,25 @@ def test_mock_value_repeated():
assert field.mock_value == "['foo_bar_value']"


def test_mock_value_map():
entry_msg = make_message(
name='SquidEntry',
fields=(
make_field(name='key', type='TYPE_STRING'),
make_field(name='value', type='TYPE_STRING'),
),
options=descriptor_pb2.MessageOptions(map_entry=True),
)
field = make_field(
name='squids',
type_name='mollusc.SquidEntry',
message=entry_msg,
label=3,
type='TYPE_MESSAGE',
)
assert field.mock_value == "{'key_value': 'value_value'}"


def test_mock_value_enum():
values = [
descriptor_pb2.EnumValueDescriptorProto(name='UNSPECIFIED', number=0),
Expand Down Expand Up @@ -227,4 +246,26 @@ def make_field(*, message=None, enum=None, **kwargs) -> wrappers.Field:
if isinstance(kwargs['type'], str):
kwargs['type'] = T.Value(kwargs['type'])
field_pb = descriptor_pb2.FieldDescriptorProto(**kwargs)
return wrappers.Field(field_pb=field_pb, message=message, enum=enum)
field = wrappers.Field(field_pb=field_pb, message=message, enum=enum)
return field


def make_message(
name, package='foo.bar.v1', module='baz', fields=(), meta=None, options=None
) -> wrappers.MessageType:
message_pb = descriptor_pb2.DescriptorProto(
name=name,
field=[i.field_pb for i in fields],
options=options,
)
return wrappers.MessageType(
message_pb=message_pb,
fields=collections.OrderedDict((i.name, i) for i in fields),
nested_messages={},
nested_enums={},
meta=meta or metadata.Metadata(address=metadata.Address(
name=name,
package=tuple(package.split('.')),
module=module,
)),
)