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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: rendering mock values for recursive messages no longer crashes #587

Merged
merged 3 commits into from
Sep 3, 2020
Merged
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
27 changes: 25 additions & 2 deletions gapic/schema/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class Field:
)
oneof: Optional[str] = None

# Arbitrary cap set via heuristic rule of thumb.
MAX_MOCK_DEPTH: int = 20

def __getattr__(self, name):
return getattr(self.field_pb, name)

Expand Down Expand Up @@ -85,6 +88,17 @@ def map(self) -> bool:

@utils.cached_property
def mock_value(self) -> str:
depth = 0
stack = [self]
answer = "{}"
while stack:
expr = stack.pop()
answer = answer.format(expr.inner_mock(stack, depth))
depth += 1

return answer

def inner_mock(self, stack, depth):
"""Return a repr of a valid, usually truthy mock value."""
# For primitives, send a truthy value computed from the
# field name.
Expand Down Expand Up @@ -113,9 +127,18 @@ def mock_value(self) -> str:
answer = f'{self.type.ident}.{mock_value.name}'

# If this is another message, set one value on the message.
if isinstance(self.type, MessageType) and len(self.type.fields):
if (
not self.map # Maps are handled separately
and isinstance(self.type, MessageType)
and len(self.type.fields)
# Nested message types need to terminate eventually
and depth < self.MAX_MOCK_DEPTH
):
sub = next(iter(self.type.fields.values()))
answer = f'{self.type.ident}({sub.name}={sub.mock_value})'
stack.append(sub)
# Don't do the recursive rendering here, just set up
# where the nested value should go with the double {}.
answer = f'{self.type.ident}({sub.name}={{}})'

if self.map:
# Maps are a special case beacuse they're represented internally as
Expand Down