예제 #1
0
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)
예제 #2
0
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))
예제 #3
0
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)
예제 #4
0
def _MassageSpecialCases(almost_snippet_values, log):
    """Catchall for converting anything fiddled-with back to pure dbroot form.

  Right now just translates enum text to numeric values.

  Args:
    almost_snippet_values: snippet values.
    log: logger obj.
  Returns:
    All the snippet values, ready to write to a dbroot.
  """
    log.debug(">massaging...")
    true_snippet_values = []
    assert isinstance(almost_snippet_values, list)
    log.debug("survived assertion")
    dbroot_proto_for_structure = dbroot_utils.MakeEmptyDbroot()
    for concrete_fieldpath, snippet_value in almost_snippet_values:
        log.debug("concrete for no good reason " + concrete_fieldpath)
        abstract_fieldpath = path_utils.AsAbstract(concrete_fieldpath)
        log.debug("abs field:" + abstract_fieldpath)

        fdesc = proto_reflection.FieldDescriptorAtFieldPath(
            dbroot_proto_for_structure, abstract_fieldpath)
        log.debug("got field desc")

        is_enum = fdesc.enum_type is not None
        log.debug("enum? " + str(is_enum))
        # Special case - on the client we represent /repeated enums/ as a choice of
        # fixed checkboxes. Here, we convert that back.
        if not is_enum:
            # plain
            log.debug("massaging, but plain: " + concrete_fieldpath + " " +
                      str(snippet_value))
            true_snippet_values.append((concrete_fieldpath, snippet_value))
            log.debug("did not massage non-enum")
        else:
            is_repeated = fdesc.label == fdesc.LABEL_REPEATED
            if not is_repeated:
                log.debug("massaging singular enum:" + concrete_fieldpath +
                          snippet_value)
                enum_val = _EnumValFromText(fdesc, snippet_value, log)
                log.debug("massaged singular; " + concrete_fieldpath + " " +
                          str(enum_val))
                true_snippet_values.append((concrete_fieldpath, enum_val))
            else:
                # repeated enum
                log.debug("supposedly repeated enum...name: %s %s" %
                          (concrete_fieldpath, str(snippet_value)))

                enum_text_vals = _ExtractWidgetEnumTextValues(
                    snippet_value, log)

                for i, enum_text in enumerate(enum_text_vals):
                    log.debug("enum text: " + enum_text)
                    log.debug("all enum vals: " + fdesc.name)
                    log.debug("all enum vals: " +
                              str(fdesc.enum_type.values_by_name.keys()))
                    enum_val = _EnumValFromText(fdesc, enum_text, log)
                    log.debug("whew, found enum val!")
                    # need to concretize, now! No way around it.
                    log.debug("special enum snippetval: " + snippet_value +
                              "->" + str(enum_val))
                    # thank heaven these can only be primitives! (& thus easy to get at)
                    added_concrete_fieldpath = concrete_fieldpath + "[%d]" % i
                    log.debug("enummed: " + added_concrete_fieldpath)

                    true_snippet_values.append(
                        (added_concrete_fieldpath, enum_val))
            log.debug("massaged enum")

    log.debug("done massaging")
    return true_snippet_values