Skip to content

Commit

Permalink
Test and impl for recursive and inclusive resource path helper funcs (#…
Browse files Browse the repository at this point in the history
…348)

More thoroughly look for resource messages:
recursively look through input messages for resources and also check
the input messages themselves.
  • Loading branch information
software-dov authored Mar 24, 2020
1 parent 5a90687 commit b2ffa9d
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 33 deletions.
20 changes: 17 additions & 3 deletions gapic/schema/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,13 @@ def __hash__(self):
def __getattr__(self, name):
return getattr(self.enum_pb, name)

@property
def resource_path(self) -> Optional[str]:
# This is a minor duck-typing workaround for the resource_messages
# property in the Service class: we need to check fields recursively
# to see if they're resources, and recursive_field_types includes enums
return None

@property
def ident(self) -> metadata.Address:
"""Return the identifier data to be used in templates."""
Expand Down Expand Up @@ -836,11 +843,18 @@ def names(self) -> FrozenSet[str]:
def resource_messages(self) -> FrozenSet[MessageType]:
"""Returns all the resource message types used in all
request fields in the service."""
def gen_resources(message):
if message.resource_path:
yield message

for type_ in message.recursive_field_types:
if type_.resource_path:
yield type_

return frozenset(
field.message
resource_msg
for method in self.methods.values()
for field in method.input.fields.values()
if field.message and field.message.resource_path
for resource_msg in gen_resources(method.input)
)

@utils.cached_property
Expand Down
92 changes: 62 additions & 30 deletions tests/unit/schema/wrappers/test_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

from test_utils.test_utils import (
get_method,
make_enum,
make_field,
make_message,
make_method,
Expand Down Expand Up @@ -156,47 +157,78 @@ def test_module_name():


def test_resource_messages():
# Resources
squid_options = descriptor_pb2.MessageOptions()
squid_options.Extensions[resource_pb2.resource].pattern.append(
"squid/{squid}")
squid_message = make_message("Squid", options=squid_options)
clam_options = descriptor_pb2.MessageOptions()
clam_options.Extensions[resource_pb2.resource].pattern.append(
"clam/{clam}")
clam_message = make_message("Clam", options=clam_options)
whelk_options = descriptor_pb2.MessageOptions()
whelk_options.Extensions[resource_pb2.resource].pattern.append(
"whelk/{whelk}")
whelk_message = make_message("Whelk", options=whelk_options)

# Not resources
octopus_message = make_message("Octopus")
oyster_message = make_message("Oyster")
nudibranch_message = make_message("Nudibranch")
# Resources are labeled via an options extension
def make_resource_opts(*args):
opts = descriptor_pb2.MessageOptions()
opts.Extensions[resource_pb2.resource].pattern.append(
"/".join("{{{arg}}}/{arg}" for arg in args)
)
return opts

# Regular, top level resource
squid_resource = make_message("Squid", options=make_resource_opts("squid"))
squid_request = make_message(
"CreateSquid",
fields=(
make_field('squid', message=squid_resource),
),
)

# Nested resource
squamosa_message = make_message(
"Squamosa",
options=make_resource_opts("clam", "squamosa"),
)
clam_resource = make_message(
"Clam",
options=make_resource_opts("clam"),
fields=(
make_field('squamosa', message=squamosa_message),
),
)
clam_request = make_message(
'CreateClam',
fields=(
make_field('clam', message=clam_resource),
# Red herring, not resources :)
make_field('zone', 2, enum=make_enum('Zone')),
make_field('pearls', 3, True, message=make_message('Pearl')),
),
)

# Some special APIs have request messages that _are_ resources.
whelk_resource = make_message("Whelk", options=make_resource_opts("whelk"))

# Not a resource
octopus_request = make_message(
"CreateOctopus",
fields=(
make_field('Octopus', message=make_message('Octopus')),
),
)

service = make_service(
'Molluscs',
methods=(
make_method(
f"Get{message.name}",
input_message=make_message(
f"{message.name}Request",
fields=[make_field(message.name, message=message)]
)
f"{message.name}",
input_message=message,
)
for message in (
squid_message,
clam_message,
whelk_message,
octopus_message,
oyster_message,
nudibranch_message
squid_request,
clam_request,
whelk_resource,
octopus_request,
)
)
)

expected = {squid_message, clam_message, whelk_message}
expected = {
squid_resource,
clam_resource,
whelk_resource,
squamosa_message,
}
actual = service.resource_messages
assert expected == actual

Expand Down

0 comments on commit b2ffa9d

Please sign in to comment.