def _IsFieldPathPrimitiveLike(fieldpath, protobuf): """Whether fieldpath is an actual primitive, or honorary primitive. We allow this latter, for our doc writers, so they don't have to fiddle + maybe get wrong, adding :value to the end of so much. Args: fieldpath: path to field. protobuf: protobuf in which to find field. Returns: whether the field at fieldpath is a primitive (true leaf) or, an honorary primitive. """ toks = path_utils.SplitAbstract(path_utils.AsAbstract(fieldpath)) fname, rest = path_utils.FirstRest(toks) fd = protobuf.DESCRIPTOR.fields_by_name.get(fname, None) if fd is None: return False while bool(rest) and fd.type == fd.TYPE_MESSAGE: fname, rest = path_utils.FirstRest(rest) fd = fd.message_type.fields_by_name.get(fname, None) if fd is None: # path contains something not in the protobuf return False # Ended of path return (not rest) and ( # .. is primitive fd.type != fd.TYPE_MESSAGE or # .. or honorary primitive path_converters.IsHonoraryPrimitive(fd.message_type.name))
def _IsFieldPathPrimitive(fieldpath, protobuf): """Whether the fieldpath is a (true) leaf in protobuf. whether protobuf structurally contains the path and, that it ends at a primitive (ie rejects subtree paths). Args: fieldpath: path of the field within the protobuf protobuf: container of the protobuf Returns: whether the fieldpath ends at a true leaf ie, value field. """ toks = path_utils.SplitAbstract(path_utils.AsAbstract(fieldpath)) fname, rest = path_utils.FirstRest(toks) fd = protobuf.DESCRIPTOR.fields_by_name.get(fname, None) if fd is None: return False while bool(rest) and fd.type == fd.TYPE_MESSAGE: fname, rest = path_utils.FirstRest(rest) fd = fd.message_type.fields_by_name.get(fname, None) if fd is None: # path contains something not in the protobuf return False # Both ended on a primitive. return (not rest) and (fd.type != fd.TYPE_MESSAGE)
def FieldpathNature(fieldpath, protobuf=None): """Returns information about the nature of a given field. Args: fieldpath: path of the field of interest protobuf: container of the field. Returns: tuple of: (whether <fieldpath> is contained in the protobuf, is true-or-honorary primitive, is strictly honorary primitive) """ if protobuf is None: protobuf = StructuralDbroot() toks = path_utils.SplitAbstract(path_utils.AsAbstract(fieldpath)) fname, rest = path_utils.FirstRest(toks) fd = protobuf.DESCRIPTOR.fields_by_name.get(fname, None) if fd is None: return (False, None, None) while bool(rest) and fd.type == fd.TYPE_MESSAGE: fname, rest = path_utils.FirstRest(rest) fd = fd.message_type.fields_by_name.get(fname, None) if fd is None: # path contains something not in the protobuf return (False, None, None) # 'poked through the bottom' of the protobuf if rest: return (False, None, None) is_true_primitive = fd.type != fd.TYPE_MESSAGE is_primitive_like = is_true_primitive or ( path_converters.IsHonoraryPrimitive(fd.message_type.name)) return (True, is_primitive_like, not is_true_primitive)
def EmptyConcretizeFieldPath(fieldpath, protobuf=None): """Adds empty concreteness markings to an abstract fieldpath. Takes an abstract path (no indices or '[]') and puts '[]' markers at repeated parts, newstyle (ie a.b.[]). We do this for reading from the template, masking file. Args: fieldpath: path of the field within the protobuf protobuf: container of the protobuf Returns: fieldpath, with empty concrete markings. """ assert path_utils.IsAbstract(fieldpath) if protobuf is None: protobuf = StructuralDbroot() toks = path_utils.SplitAbstract(fieldpath) empty_concrete_toks = [] def AddElement(fname, fd): empty_concrete_toks.append(fname) if fd.label == fd.LABEL_REPEATED: empty_concrete_toks.append("[]") def GetNext(toks, fd): fname, rest = path_utils.FirstRest(toks) fd = fd.message_type.fields_by_name.get(fname, None) if fd is None: assert False, "bad path: %s, at: %s" % (fieldpath, fname) return fname, rest, fd fname, rest = path_utils.FirstRest(toks) fd = protobuf.DESCRIPTOR.fields_by_name.get(fname, None) if fd is None: assert False, "bad path: %s, at: %s" % (fieldpath, fname) AddElement(fname, fd) while bool(rest) and fd.type == fd.TYPE_MESSAGE: fname, rest, fd = GetNext(rest, fd) AddElement(fname, fd) assert (not rest) and (fd.type != fd.TYPE_MESSAGE), ( "path %s incomplete or something" % fieldpath) return ".".join(empty_concrete_toks)