Python google.protobuf() Examples

The following are 24 code examples of google.protobuf(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module google , or try the search function .
Example #1
Source File: MyCaffe.py    From onnx2caffe with MIT License 6 votes vote down vote up
def assign_proto(proto, name, val):
    """Assign a Python object to a protobuf message, based on the Python
    type (in recursive fashion). Lists become repeated fields/messages, dicts
    become messages, and other types are assigned directly. For convenience,
    repeated fields whose values are not lists are converted to single-element
    lists; e.g., `my_repeated_int_field=3` is converted to
    `my_repeated_int_field=[3]`."""

    is_repeated_field = hasattr(getattr(proto, name), 'extend')
    if is_repeated_field and not isinstance(val, list):
        val = [val]
    if isinstance(val, list):
        if isinstance(val[0], dict):
            for item in val:
                proto_item = getattr(proto, name).add()
                for k, v in six.iteritems(item):
                    assign_proto(proto_item, k, v)
        else:
            getattr(proto, name).extend(val)
    elif isinstance(val, dict):
        for k, v in six.iteritems(val):
            assign_proto(getattr(proto, name), k, v)
    else:
        setattr(proto, name, val) 
Example #2
Source File: net_spec.py    From Deep-Learning-Based-Structural-Damage-Detection with MIT License 6 votes vote down vote up
def assign_proto(proto, name, val):
    """Assign a Python object to a protobuf message, based on the Python
    type (in recursive fashion). Lists become repeated fields/messages, dicts
    become messages, and other types are assigned directly. For convenience,
    repeated fields whose values are not lists are converted to single-element
    lists; e.g., `my_repeated_int_field=3` is converted to
    `my_repeated_int_field=[3]`."""

    is_repeated_field = hasattr(getattr(proto, name), 'extend')
    if is_repeated_field and not isinstance(val, list):
        val = [val]
    if isinstance(val, list):
        if isinstance(val[0], dict):
            for item in val:
                proto_item = getattr(proto, name).add()
                for k, v in six.iteritems(item):
                    assign_proto(proto_item, k, v)
        else:
            getattr(proto, name).extend(val)
    elif isinstance(val, dict):
        for k, v in six.iteritems(val):
            assign_proto(getattr(proto, name), k, v)
    else:
        setattr(proto, name, val) 
Example #3
Source File: net_spec.py    From mix-and-match with MIT License 6 votes vote down vote up
def assign_proto(proto, name, val):
    """Assign a Python object to a protobuf message, based on the Python
    type (in recursive fashion). Lists become repeated fields/messages, dicts
    become messages, and other types are assigned directly."""

    if isinstance(val, list):
        if isinstance(val[0], dict):
            for item in val:
                proto_item = getattr(proto, name).add()
                for k, v in six.iteritems(item):
                    assign_proto(proto_item, k, v)
        else:
            getattr(proto, name).extend(val)
    elif isinstance(val, dict):
        for k, v in six.iteritems(val):
            assign_proto(getattr(proto, name), k, v)
    else:
        setattr(proto, name, val) 
Example #4
Source File: __main__.py    From luci-py with Apache License 2.0 6 votes vote down vote up
def fix_protobuf_package():
  """Ensures that the bundled version of protobuf is used.

  Inspired by components/utils.py
  """
  # In some system, google is preloaded when using runit.py, which is implicitly
  # loaded by using the zip support, as used with swarming_bot.zip. Using
  # 'python -s -S' doesn't work to skip 'import site' in this case. So use the
  # nuclear option, unload the package if found.
  if 'google' in sys.modules:
    del sys.modules['google']
  # Completely zap out preinstalled google. This works because package google
  # itself has no functionality.
  path_to_google = os.path.join(THIS_FILE, 'third_party', 'google')
  import google
  google.__path__.insert(0, path_to_google)
  del google.__path__[1:]

  # Sanity check.
  import google.protobuf
  # pylint: disable=unused-variable
  from google.protobuf import symbol_database


# Then it's safe to import the rest. 
Example #5
Source File: api.py    From recipes-py with Apache License 2.0 6 votes vote down vote up
def build(self):
    """Returns current build as a `buildbucket.v2.Build` protobuf message.

    For value format, see `Build` message in
    [build.proto](https://chromium.googlesource.com/infra/luci/luci-go/+/master/buildbucket/proto/build.proto).

    DO NOT MODIFY the returned value.
    Do not implement conditional logic on returned tags; they are for indexing.
    Use returned `build.input` instead.

    Pure Buildbot support: to simplify transition to buildbucket, returns a
    message even if the current build is not a buildbucket build. Provides as
    much information as possible. Some fields may be left empty, violating
    the rules described in the .proto files.
    If the current build is not a buildbucket build, returned `build.id` is 0.
    """
    return self._build 
Example #6
Source File: spearmint_april2013_mod.py    From HPOlib with GNU General Public License v3.0 6 votes vote down vote up
def check_dependencies(self):
        try:
            import google.protobuf
        except ImportError:
            raise ImportError("Google protobuf cannot be imported. Are you sure "
                              "it's  installed?")
        try:
            import numpy
        except ImportError:
            raise ImportError("Numpy cannot be imported. Are you sure that it's"
                              " installed?")
        try:
            import scipy
        except ImportError:
            raise ImportError("Scipy cannot be imported. Are you sure that it's"
                              " installed?") 
Example #7
Source File: spearmint_gitfork_mod.py    From HPOlib with GNU General Public License v3.0 6 votes vote down vote up
def check_dependencies(self):
        try:
            import google.protobuf
            try:
                from google.protobuf.internal import enum_type_wrapper
            except ImportError:
                raise ImportError("Installed google.protobuf version is too old, "
                                  "you need at least 2.5.0")
        except ImportError:
            raise ImportError("Google protobuf cannot be imported. Are you sure "
                              "it's  installed?")
        try:
            import numpy
        except ImportError:
            raise ImportError("Numpy cannot be imported. Are you sure that it's"
                              " installed?")
        try:
            import scipy
        except ImportError:
            raise ImportError("Scipy cannot be imported. Are you sure that it's"
                              " installed?") 
Example #8
Source File: field_masks.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def advance_to_field(self, field):
    """Advances the context to the next message field.

    Args:
      field: a google.protobuf.descriptor.FieldDescriptor to move to.
    """
    self.desc = field.message_type
    self.repeated = field.label == descriptor.FieldDescriptor.LABEL_REPEATED
    self._field_path.append(field.name) 
Example #9
Source File: field_masks.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def advance_to_field(self, field):
    """Advances the context to the next message field.

    Args:
      field: a google.protobuf.descriptor.FieldDescriptor to move to.
    """
    self.desc = field.message_type
    self.repeated = field.label == descriptor.FieldDescriptor.LABEL_REPEATED
    self._field_path.append(field.name) 
Example #10
Source File: field_masks.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def merge(self, src, dest):
    """Merges masked fields from src to dest.

    Merges even empty/unset fields, as long as they are present in the mask.

    Overwrites repeated/map fields entirely. Does not support partial updates of
    such fields.
    """
    assert isinstance(src, protobuf.message.Message)
    assert type(src) == type(dest)  # pylint: disable=unidiomatic-typecheck

    for f_name, submask in self.children.items():
      include_partially = bool(submask.children)

      dest_value = getattr(dest, f_name)
      src_value = getattr(src, f_name)

      f_desc = dest.DESCRIPTOR.fields_by_name[f_name]
      is_repeated = f_desc.label == descriptor.FieldDescriptor.LABEL_REPEATED
      is_message = f_desc.type == descriptor.FieldDescriptor.TYPE_MESSAGE

      # Only non-repeated submessages can be merged partially.
      if include_partially and is_message and not is_repeated:
        submask.merge(src_value, dest_value)
      # Otherwise overwrite entirely.
      elif is_repeated:
        dest.ClearField(f_name)
        dest_value = getattr(dest, f_name)  # restore after ClearField.
        dest_value.extend(src_value)
      elif is_message:
        dest_value.CopyFrom(src_value)
      else:
        # Scalar value.
        setattr(dest, f_name, src_value) 
Example #11
Source File: field_masks.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def advance_to_field(self, field):
    """Advances the context to the next message field.

    Args:
      field: a google.protobuf.descriptor.FieldDescriptor to move to.
    """
    self.desc = field.message_type
    self.repeated = field.label == descriptor.FieldDescriptor.LABEL_REPEATED
    self._field_path.append(field.name) 
Example #12
Source File: field_masks.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def merge(self, src, dest):
    """Merges masked fields from src to dest.

    Merges even empty/unset fields, as long as they are present in the mask.

    Overwrites repeated/map fields entirely. Does not support partial updates of
    such fields.
    """
    assert isinstance(src, protobuf.message.Message)
    assert type(src) == type(dest)  # pylint: disable=unidiomatic-typecheck

    for f_name, submask in self.children.items():
      include_partially = bool(submask.children)

      dest_value = getattr(dest, f_name)
      src_value = getattr(src, f_name)

      f_desc = dest.DESCRIPTOR.fields_by_name[f_name]
      is_repeated = f_desc.label == descriptor.FieldDescriptor.LABEL_REPEATED
      is_message = f_desc.type == descriptor.FieldDescriptor.TYPE_MESSAGE

      # Only non-repeated submessages can be merged partially.
      if include_partially and is_message and not is_repeated:
        submask.merge(src_value, dest_value)
      # Otherwise overwrite entirely.
      elif is_repeated:
        dest.ClearField(f_name)
        dest_value = getattr(dest, f_name)  # restore after ClearField.
        dest_value.extend(src_value)
      elif is_message:
        dest_value.CopyFrom(src_value)
      else:
        # Scalar value.
        setattr(dest, f_name, src_value) 
Example #13
Source File: field_masks.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def merge(self, src, dest):
    """Merges masked fields from src to dest.

    Merges even empty/unset fields, as long as they are present in the mask.

    Overwrites repeated/map fields entirely. Does not support partial updates of
    such fields.
    """
    assert isinstance(src, protobuf.message.Message)
    assert type(src) == type(dest)  # pylint: disable=unidiomatic-typecheck

    for f_name, submask in self.children.items():
      include_partially = bool(submask.children)

      dest_value = getattr(dest, f_name)
      src_value = getattr(src, f_name)

      f_desc = dest.DESCRIPTOR.fields_by_name[f_name]
      is_repeated = f_desc.label == descriptor.FieldDescriptor.LABEL_REPEATED
      is_message = f_desc.type == descriptor.FieldDescriptor.TYPE_MESSAGE

      # Only non-repeated submessages can be merged partially.
      if include_partially and is_message and not is_repeated:
        submask.merge(src_value, dest_value)
      # Otherwise overwrite entirely.
      elif is_repeated:
        dest.ClearField(f_name)
        dest_value = getattr(dest, f_name)  # restore after ClearField.
        dest_value.extend(src_value)
      elif is_message:
        dest_value.CopyFrom(src_value)
      else:
        # Scalar value.
        setattr(dest, f_name, src_value) 
Example #14
Source File: field_masks.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def advance_to_field(self, field):
    """Advances the context to the next message field.

    Args:
      field: a google.protobuf.descriptor.FieldDescriptor to move to.
    """
    self.desc = field.message_type
    self.repeated = field.label == descriptor.FieldDescriptor.LABEL_REPEATED
    self._field_path.append(field.name) 
Example #15
Source File: field_masks.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def merge(self, src, dest):
    """Merges masked fields from src to dest.

    Merges even empty/unset fields, as long as they are present in the mask.

    Overwrites repeated/map fields entirely. Does not support partial updates of
    such fields.
    """
    assert isinstance(src, protobuf.message.Message)
    assert type(src) == type(dest)  # pylint: disable=unidiomatic-typecheck

    for f_name, submask in self.children.items():
      include_partially = bool(submask.children)

      dest_value = getattr(dest, f_name)
      src_value = getattr(src, f_name)

      f_desc = dest.DESCRIPTOR.fields_by_name[f_name]
      is_repeated = f_desc.label == descriptor.FieldDescriptor.LABEL_REPEATED
      is_message = f_desc.type == descriptor.FieldDescriptor.TYPE_MESSAGE

      # Only non-repeated submessages can be merged partially.
      if include_partially and is_message and not is_repeated:
        submask.merge(src_value, dest_value)
      # Otherwise overwrite entirely.
      elif is_repeated:
        dest.ClearField(f_name)
        dest_value = getattr(dest, f_name)  # restore after ClearField.
        dest_value.extend(src_value)
      elif is_message:
        dest_value.CopyFrom(src_value)
      else:
        # Scalar value.
        setattr(dest, f_name, src_value) 
Example #16
Source File: field_masks.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def advance_to_field(self, field):
    """Advances the context to the next message field.

    Args:
      field: a google.protobuf.descriptor.FieldDescriptor to move to.
    """
    self.desc = field.message_type
    self.repeated = field.label == descriptor.FieldDescriptor.LABEL_REPEATED
    self._field_path.append(field.name) 
Example #17
Source File: field_masks.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def merge(self, src, dest):
    """Merges masked fields from src to dest.

    Merges even empty/unset fields, as long as they are present in the mask.

    Overwrites repeated/map fields entirely. Does not support partial updates of
    such fields.
    """
    assert isinstance(src, protobuf.message.Message)
    assert type(src) == type(dest)  # pylint: disable=unidiomatic-typecheck

    for f_name, submask in self.children.items():
      include_partially = bool(submask.children)

      dest_value = getattr(dest, f_name)
      src_value = getattr(src, f_name)

      f_desc = dest.DESCRIPTOR.fields_by_name[f_name]
      is_repeated = f_desc.label == descriptor.FieldDescriptor.LABEL_REPEATED
      is_message = f_desc.type == descriptor.FieldDescriptor.TYPE_MESSAGE

      # Only non-repeated submessages can be merged partially.
      if include_partially and is_message and not is_repeated:
        submask.merge(src_value, dest_value)
      # Otherwise overwrite entirely.
      elif is_repeated:
        dest.ClearField(f_name)
        dest_value = getattr(dest, f_name)  # restore after ClearField.
        dest_value.extend(src_value)
      elif is_message:
        dest_value.CopyFrom(src_value)
      else:
        # Scalar value.
        setattr(dest, f_name, src_value) 
Example #18
Source File: field_masks.py    From luci-py with Apache License 2.0 4 votes vote down vote up
def trim(self, message):
    """Clears message fields that are not in the mask.

    The message must be a google.protobuf.message.Message.
    Uses self.includes to decide what to trim, see its docstring.
    If self is a leaf, this is a noop.
    """
    for f, v in message.ListFields():
      incl = self._includes((f.name,))
      if incl == INCLUDE_ENTIRELY:
        continue

      if incl == EXCLUDE:
        message.ClearField(f.name)
        continue

      assert incl == INCLUDE_PARTIALLY
      # Child for this field must exist because INCLUDE_PARTIALLY.
      child = self.children[f.name]

      if not f.message_type:
        # The field is scalar, but the field mask does not specify to
        # include it entirely. Skip it because scalars do not have
        # subfields. Note that from_field_mask would fail on such a mask
        # because a scalar field cannot be followed by other fields.
        message.ClearField(f.name)
        continue

      # Trim the field value.
      if f.message_type.GetOptions().map_entry:
        for mk, mv in v.items():
          incl = self._includes((f.name, mk))
          if incl == INCLUDE_ENTIRELY:
            pass
          elif incl == EXCLUDE:
            v.pop(mk)
          elif isinstance(mv, protobuf.message.Message):
            assert incl == INCLUDE_PARTIALLY
            # Child for mk must exist because INCLUDE_PARTIALLY.
            child.children[mk].trim(mv)
          else:
            # The field is scalar, see the comment above.
            v.pop(mk)
      elif f.label == descriptor.FieldDescriptor.LABEL_REPEATED:
        star_child = child.children[STAR]
        for rv in v:
          star_child.trim(rv)
      else:
        child.trim(v) 
Example #19
Source File: field_masks.py    From luci-py with Apache License 2.0 4 votes vote down vote up
def trim(self, message):
    """Clears message fields that are not in the mask.

    The message must be a google.protobuf.message.Message.
    Uses self.includes to decide what to trim, see its docstring.
    If self is a leaf, this is a noop.
    """
    for f, v in message.ListFields():
      incl = self._includes((f.name,))
      if incl == INCLUDE_ENTIRELY:
        continue

      if incl == EXCLUDE:
        message.ClearField(f.name)
        continue

      assert incl == INCLUDE_PARTIALLY
      # Child for this field must exist because INCLUDE_PARTIALLY.
      child = self.children[f.name]

      if not f.message_type:
        # The field is scalar, but the field mask does not specify to
        # include it entirely. Skip it because scalars do not have
        # subfields. Note that from_field_mask would fail on such a mask
        # because a scalar field cannot be followed by other fields.
        message.ClearField(f.name)
        continue

      # Trim the field value.
      if f.message_type.GetOptions().map_entry:
        for mk, mv in v.items():
          incl = self._includes((f.name, mk))
          if incl == INCLUDE_ENTIRELY:
            pass
          elif incl == EXCLUDE:
            v.pop(mk)
          elif isinstance(mv, protobuf.message.Message):
            assert incl == INCLUDE_PARTIALLY
            # Child for mk must exist because INCLUDE_PARTIALLY.
            child.children[mk].trim(mv)
          else:
            # The field is scalar, see the comment above.
            v.pop(mk)
      elif f.label == descriptor.FieldDescriptor.LABEL_REPEATED:
        star_child = child.children[STAR]
        for rv in v:
          star_child.trim(rv)
      else:
        child.trim(v) 
Example #20
Source File: field_masks.py    From luci-py with Apache License 2.0 4 votes vote down vote up
def trim(self, message):
    """Clears message fields that are not in the mask.

    The message must be a google.protobuf.message.Message.
    Uses self.includes to decide what to trim, see its docstring.
    If self is a leaf, this is a noop.
    """
    for f, v in message.ListFields():
      incl = self._includes((f.name,))
      if incl == INCLUDE_ENTIRELY:
        continue

      if incl == EXCLUDE:
        message.ClearField(f.name)
        continue

      assert incl == INCLUDE_PARTIALLY
      # Child for this field must exist because INCLUDE_PARTIALLY.
      child = self.children[f.name]

      if not f.message_type:
        # The field is scalar, but the field mask does not specify to
        # include it entirely. Skip it because scalars do not have
        # subfields. Note that from_field_mask would fail on such a mask
        # because a scalar field cannot be followed by other fields.
        message.ClearField(f.name)
        continue

      # Trim the field value.
      if f.message_type.GetOptions().map_entry:
        for mk, mv in v.items():
          incl = self._includes((f.name, mk))
          if incl == INCLUDE_ENTIRELY:
            pass
          elif incl == EXCLUDE:
            v.pop(mk)
          elif isinstance(mv, protobuf.message.Message):
            assert incl == INCLUDE_PARTIALLY
            # Child for mk must exist because INCLUDE_PARTIALLY.
            child.children[mk].trim(mv)
          else:
            # The field is scalar, see the comment above.
            v.pop(mk)
      elif f.label == descriptor.FieldDescriptor.LABEL_REPEATED:
        star_child = child.children[STAR]
        for rv in v:
          star_child.trim(rv)
      else:
        child.trim(v) 
Example #21
Source File: field_masks.py    From luci-py with Apache License 2.0 4 votes vote down vote up
def from_field_mask(
      cls, field_mask, desc, json_names=False, update_mask=False):
    """Parses a field mask to a Mask.

    Removes trailing stars, e.g. parses ['a.*'] as ['a'].
    Removes redundant paths, e.g. parses ['a', 'a.b'] as ['a'].

    Args:
      field_mask: a google.protobuf.field_mask_pb2.FieldMask instance.
      desc: a google.protobuf.descriptor.Descriptor for the target message.
      json_names: True if field_mask uses json field names for field names,
        e.g. "fooBar" instead of "foo_bar".
        Field names will be parsed in the canonical form.
      update_mask: if True, the field_mask is treated as an update mask.
        In an update mask, a repeated field is allowed only as the last
        field in a paths string.

    Raises:
      ValueError if a field path is invalid.
    """
    parsed_paths = []
    for p in field_mask.paths:
      try:
        parsed_paths.append(_parse_path(p, desc, json_names=json_names)[0])
      except ValueError as ex:
        raise ValueError('invalid path "%s": %s' % (p, ex))

    parsed_paths = _normalize_paths(parsed_paths)

    root = cls(desc)
    for i, p in enumerate(parsed_paths):
      node = root
      node_name = ''
      for seg in p:
        if node.repeated and update_mask:
          raise ValueError(
              ('update mask allows a repeated field only at the last '
               'position; field "%s" in "%s" is not last')
              % (node_name, field_mask.paths[i]))
        if seg not in node.children:
          if node.desc.GetOptions().map_entry:
            child = cls(node.desc.fields_by_name['value'].message_type)
          elif node.repeated:
            child = cls(node.desc)
          else:
            field = node.desc.fields_by_name[seg]
            repeated = field.label == descriptor.FieldDescriptor.LABEL_REPEATED
            child = cls(field.message_type, repeated=repeated)
          node.children[seg] = child
        node = node.children[seg]
        node_name = seg
    return root 
Example #22
Source File: field_masks.py    From luci-py with Apache License 2.0 4 votes vote down vote up
def from_field_mask(
      cls, field_mask, desc, json_names=False, update_mask=False):
    """Parses a field mask to a Mask.

    Removes trailing stars, e.g. parses ['a.*'] as ['a'].
    Removes redundant paths, e.g. parses ['a', 'a.b'] as ['a'].

    Args:
      field_mask: a google.protobuf.field_mask_pb2.FieldMask instance.
      desc: a google.protobuf.descriptor.Descriptor for the target message.
      json_names: True if field_mask uses json field names for field names,
        e.g. "fooBar" instead of "foo_bar".
        Field names will be parsed in the canonical form.
      update_mask: if True, the field_mask is treated as an update mask.
        In an update mask, a repeated field is allowed only as the last
        field in a paths string.

    Raises:
      ValueError if a field path is invalid.
    """
    parsed_paths = []
    for p in field_mask.paths:
      try:
        parsed_paths.append(_parse_path(p, desc, json_names=json_names)[0])
      except ValueError as ex:
        raise ValueError('invalid path "%s": %s' % (p, ex))

    parsed_paths = _normalize_paths(parsed_paths)

    root = cls(desc)
    for i, p in enumerate(parsed_paths):
      node = root
      node_name = ''
      for seg in p:
        if node.repeated and update_mask:
          raise ValueError(
              ('update mask allows a repeated field only at the last '
               'position; field "%s" in "%s" is not last')
              % (node_name, field_mask.paths[i]))
        if seg not in node.children:
          if node.desc.GetOptions().map_entry:
            child = cls(node.desc.fields_by_name['value'].message_type)
          elif node.repeated:
            child = cls(node.desc)
          else:
            field = node.desc.fields_by_name[seg]
            repeated = field.label == descriptor.FieldDescriptor.LABEL_REPEATED
            child = cls(field.message_type, repeated=repeated)
          node.children[seg] = child
        node = node.children[seg]
        node_name = seg
    return root 
Example #23
Source File: field_masks.py    From luci-py with Apache License 2.0 4 votes vote down vote up
def from_field_mask(
      cls, field_mask, desc, json_names=False, update_mask=False):
    """Parses a field mask to a Mask.

    Removes trailing stars, e.g. parses ['a.*'] as ['a'].
    Removes redundant paths, e.g. parses ['a', 'a.b'] as ['a'].

    Args:
      field_mask: a google.protobuf.field_mask_pb2.FieldMask instance.
      desc: a google.protobuf.descriptor.Descriptor for the target message.
      json_names: True if field_mask uses json field names for field names,
        e.g. "fooBar" instead of "foo_bar".
        Field names will be parsed in the canonical form.
      update_mask: if True, the field_mask is treated as an update mask.
        In an update mask, a repeated field is allowed only as the last
        field in a paths string.

    Raises:
      ValueError if a field path is invalid.
    """
    parsed_paths = []
    for p in field_mask.paths:
      try:
        parsed_paths.append(_parse_path(p, desc, json_names=json_names)[0])
      except ValueError as ex:
        raise ValueError('invalid path "%s": %s' % (p, ex))

    parsed_paths = _normalize_paths(parsed_paths)

    root = cls(desc)
    for i, p in enumerate(parsed_paths):
      node = root
      node_name = ''
      for seg in p:
        if node.repeated and update_mask:
          raise ValueError(
              ('update mask allows a repeated field only at the last '
               'position; field "%s" in "%s" is not last')
              % (node_name, field_mask.paths[i]))
        if seg not in node.children:
          if node.desc.GetOptions().map_entry:
            child = cls(node.desc.fields_by_name['value'].message_type)
          elif node.repeated:
            child = cls(node.desc)
          else:
            field = node.desc.fields_by_name[seg]
            repeated = field.label == descriptor.FieldDescriptor.LABEL_REPEATED
            child = cls(field.message_type, repeated=repeated)
          node.children[seg] = child
        node = node.children[seg]
        node_name = seg
    return root 
Example #24
Source File: field_masks.py    From luci-py with Apache License 2.0 4 votes vote down vote up
def from_field_mask(
      cls, field_mask, desc, json_names=False, update_mask=False):
    """Parses a field mask to a Mask.

    Removes trailing stars, e.g. parses ['a.*'] as ['a'].
    Removes redundant paths, e.g. parses ['a', 'a.b'] as ['a'].

    Args:
      field_mask: a google.protobuf.field_mask_pb2.FieldMask instance.
      desc: a google.protobuf.descriptor.Descriptor for the target message.
      json_names: True if field_mask uses json field names for field names,
        e.g. "fooBar" instead of "foo_bar".
        Field names will be parsed in the canonical form.
      update_mask: if True, the field_mask is treated as an update mask.
        In an update mask, a repeated field is allowed only as the last
        field in a paths string.

    Raises:
      ValueError if a field path is invalid.
    """
    parsed_paths = []
    for p in field_mask.paths:
      try:
        parsed_paths.append(_parse_path(p, desc, json_names=json_names)[0])
      except ValueError as ex:
        raise ValueError('invalid path "%s": %s' % (p, ex))

    parsed_paths = _normalize_paths(parsed_paths)

    root = cls(desc)
    for i, p in enumerate(parsed_paths):
      node = root
      node_name = ''
      for seg in p:
        if node.repeated and update_mask:
          raise ValueError(
              ('update mask allows a repeated field only at the last '
               'position; field "%s" in "%s" is not last')
              % (node_name, field_mask.paths[i]))
        if seg not in node.children:
          if node.desc.GetOptions().map_entry:
            child = cls(node.desc.fields_by_name['value'].message_type)
          elif node.repeated:
            child = cls(node.desc)
          else:
            field = node.desc.fields_by_name[seg]
            repeated = field.label == descriptor.FieldDescriptor.LABEL_REPEATED
            child = cls(field.message_type, repeated=repeated)
          node.children[seg] = child
        node = node.children[seg]
        node_name = seg
    return root