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

Add final set of protobuf helpers to api_core #4259

Merged
merged 3 commits into from Oct 26, 2017

Conversation

theacodes
Copy link
Contributor

Closes #3842

Note: this is directly ported from gax, barring minor changes, this code has already been reviewed.

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Oct 25, 2017
Copy link
Contributor

@dhermes dhermes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is surprisingly complex


def _resolve_subkeys(key, separator='.'):
"""Given a key which may actually be a nested key, return the top level
key and any nested subkeys as separate values.

This comment was marked as spam.

This comment was marked as spam.

if separator in key:
index = key.index(separator)
subkey = key[index + 1:]
key = key[:index]

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

default is generally recommended, as protobuf messages almost
always have default values for unset values and it is not always
possible to tell the difference between a falsy value and an
unset one. If no default is set then raises :class:`KeyError` will

This comment was marked as spam.

This comment was marked as spam.

# Attempt to get the value from the two types of objects we know about.
# If we get something else, complain.
if isinstance(msg_or_dict, Message):
answer = getattr(msg_or_dict, key, default)

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

raise KeyError(key)

# If a subkey exists, call this method recursively against the answer.
if subkey and answer is not default:

This comment was marked as spam.

This comment was marked as spam.

type(msg_or_dict)))

# We may be setting a nested key. Resolve this.
key, subkey = _resolve_subkeys(key)

This comment was marked as spam.

This comment was marked as spam.

# If a subkey exists, then get that object and call this method
# recursively against it using the subkey.
if subkey is not None:
if isinstance(msg_or_dict, collections.MutableMapping):

This comment was marked as spam.

This comment was marked as spam.



def setdefault(msg_or_dict, key, value):
"""Set the key on a protobuf Message or dictioanary to a given value if the

This comment was marked as spam.

This comment was marked as spam.

current value is falsy.

Because protobuf Messages do not distinguish between unset values and
falsy ones particularly well, this method treats any falsy value

This comment was marked as spam.

This comment was marked as spam.

# Clear the existing repeated protobuf message of any elements
# currently inside it.
while getattr(msg, key):
getattr(msg, key).pop()

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

if isinstance(item, collections.Mapping):
getattr(msg, key).add(**item)
else:
getattr(msg, key).extend([item])

This comment was marked as spam.

This comment was marked as spam.

elif isinstance(value, Message):
# Assign the protobuf message values to the protobuf message.
for item_key, item_value in value.ListFields():
set(getattr(msg, key), item_key.name, item_value)

This comment was marked as spam.

This comment was marked as spam.

def _set_field_on_message(msg, key, value):
"""Set helper for protobuf Messages."""
# Attempt to set the value on the types of objects we know how to deal
# with.

This comment was marked as spam.

getattr(msg, key).add(**item)
else:
getattr(msg, key).extend([item])
elif isinstance(value, collections.Mapping):

This comment was marked as spam.

This comment was marked as spam.

@theacodes theacodes merged commit 4c24da3 into googleapis:master Oct 26, 2017
@theacodes theacodes deleted the api-core-proto-helpers branch October 26, 2017 19:13
@theacodes theacodes added this to Done in google.api.core Oct 26, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: core cla: yes This human has signed the Contributor License Agreement.
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

4 participants