示例#1
0
    def _get_field_option(field: FieldDescriptor, option, default_value):
        options: MessageOptions = field.GetOptions()

        if options.HasExtension(option):
            return options.Extensions[option]
        else:
            return default_value
示例#2
0
def field_gen(buf: Buffer, field: FieldDescriptor, code_path: List[str],
              proto_path: List[str]) -> None:
    for opt, opt_value in field.GetOptions().ListFields():
        if opt.full_name == "validate.rules":
            dispatch_field(buf, field, code_path, proto_path, opt_value)
            if opt_value.HasField("message"):
                assert field.message_type
                if opt_value.message.skip:
                    return

    if field.message_type:
        for opt, opt_value in field.message_type.GetOptions().ListFields():
            if (opt.full_name == "google.protobuf.MessageOptions.map_entry"
                    and opt_value is True):
                return
        field_value = ".".join(code_path)
        if field.label == FieldDescriptor.LABEL_REPEATED:
            buf.add(f"for item in {field_value}:")
            with buf.indent():
                buf.add("validate(item)")
        else:
            outer = ".".join(code_path[:-1])
            inner = code_path[-1]
            buf.add(f'if {outer}.HasField("{inner}"):')
            with buf.indent():
                buf.add(f"validate({field_value})")
示例#3
0
def _validate_reference_field(parent: message.Message,
                              field: descriptor.FieldDescriptor):
    """Ensure that the provided reference field is valid.

  Args:
    parent: The containing Message.
    field: The reference field descriptor.

  Raises:
    fhir_errors.InvalidFhirError: In the event of an empty reference (no
    extensions, no identifier, no display).
  """
    oneof = field.message_type.oneofs[0]

    # Singular fields have a length of 1
    for i in range(proto_utils.field_content_length(parent, field)):
        reference = proto_utils.get_value_at_field_index(parent, field, i)
        reference_field_name = reference.WhichOneof(oneof.name)

        if reference_field_name is None:
            if not (reference.extension or reference.HasField('identifier')
                    or reference.HasField('display')):
                raise fhir_errors.InvalidFhirError(
                    f'`{reference.DESCRIPTOR.name}` is an empty reference.')
            # There's no reference field, but there is other data. This is valid.
            return

        field_options = field.GetOptions()
        if not field_options.Extensions[annotations_pb2.valid_reference_type]:
            # The reference field does not have restrictions, so any value is fine.
            return

        if reference.HasField('uri') or reference.HasField('fragment'):
            # Uri and Fragment references are untyped.
            return

        # There are no reference annotations for DSTU2; skip validation
        if annotation_utils.get_fhir_version(
                reference) == annotations_pb2.FhirVersion.DSTU2:
            return

        reference_field = reference.DESCRIPTOR.fields_by_name[
            reference_field_name]
        if annotation_utils.is_typed_reference_field(reference_field):
            # Ensure that the reference type is listed as "valid"
            reference_type = reference_field.GetOptions().Extensions[
                annotations_pb2.referenced_fhir_type]
            is_allowed = False
            for valid_type in field_options.Extensions[
                    annotations_pb2.valid_reference_type]:
                if valid_type == reference_type or valid_type == 'Resource':
                    is_allowed = True
                    break

            if not is_allowed:
                raise fhir_errors.InvalidFhirError(
                    f'Message `{parent.DESCRIPTOR.full_name}` contains an invalid '
                    f'reference type: `{reference_type}` set at: '
                    f'`{reference_field_name}`.')
示例#4
0
def make_lback_protobuf_field(name,
                              type,
                              type1,
                              idx=0,
                              tag=0,
                              default_value=""):
    return FieldDescriptor(name, name, idx, tag, type, type1, default_value,
                           name, None, None, None, False, None)
示例#5
0
def _get_pretty_value(value: Any, desc: descriptor.FieldDescriptor,
                      components: List[Text]) -> Dict[Text, List[Any]]:
    """Converts value to the object easier to work with or more representative.

  Args:
    value: Object to transform.
    desc: Field descriptor of a value.
    components: Prefixes for column names.

  Returns:
    Data dictionary representing the given value.
  """
    data = {}
    column_name = '.'.join(components + [desc.name])
    sem_type = semantic_pb2.sem_type

    if desc.label == desc.LABEL_REPEATED:
        data[column_name] = [from_sequence(value)]

    elif desc.type == desc.TYPE_ENUM:
        char_name = next(_.name for _ in desc.enum_type.values
                         if _.number == value)
        data[column_name] = [char_name]

    elif desc.type == desc.TYPE_BYTES:
        data[column_name] = [value]
        data[column_name + '.pretty'] = [repr(value)]

    elif desc.GetOptions().Extensions[sem_type].type == 'RDFDatetime':
        data[column_name] = [value]
        pretty_value = datetime.datetime.utcfromtimestamp(value / (10**6))
        data[column_name + '.pretty'] = [pretty_value]

    elif desc.GetOptions().Extensions[sem_type].type == 'StatMode':
        data[column_name] = [value]
        data[column_name + '.pretty'] = [stat.mode_from_bitmask(value)]

    else:
        data[column_name] = [value]

    return data
示例#6
0
def convert_proto_type_to_click_house_type(
        field_descriptor: FieldDescriptor) -> str:
    if field_descriptor.message_type:
        message_name = field_descriptor.message_type.name
        raise UnknownMessageError(
            f"Can't convert field with type message of {message_name} to Clickhouse type"
        )

    field_meta = field_descriptor.GetOptions().Extensions[
        options_pb2.field_meta]
    if field_meta.clickhouse_data_type:
        ch_type = field_meta.clickhouse_data_type
    else:
        try:
            ch_type = TYPES_MAPPING[field_descriptor.type]
        except KeyError:
            raise UnknownFieldError(
                f"Can't convert field with type {field_descriptor.type} to Clickhouse type"
            )

    if field_descriptor.label == FieldDescriptor.LABEL_REPEATED:
        return f'Array({ch_type})'

    return ch_type
 def _field_options(self, field: FieldDescriptor, provider: FieldDescriptor = None):
     provider = provider or self._BREWBLOX_PROVIDER
     return field.GetOptions().Extensions[provider]
示例#8
0
def MakeClassDescriptor(descriptor_pool,
                        desc_proto,
                        package='',
                        build_file_if_cpp=True,
                        syntax=None):
    if api_implementation.Type() == 'cpp' and build_file_if_cpp:
        # The C++ implementation requires all descriptors to be backed by the same
        # definition in the C++ descriptor pool. To do this, we build a
        # FileDescriptorProto with the same definition as this descriptor and build
        # it into the pool.
        from google.protobuf import descriptor_pb2
        file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
        file_descriptor_proto.message_type.add().MergeFrom(desc_proto)

        # Generate a random name for this proto file to prevent conflicts with any
        # imported ones. We need to specify a file name so the descriptor pool
        # accepts our FileDescriptorProto, but it is not important what that file
        # name is actually set to.
        proto_name = binascii.hexlify(os.urandom(16)).decode('ascii')

        if package:
            file_descriptor_proto.name = os.path.join(
                package.replace('.', '/'), proto_name + '.proto')
            file_descriptor_proto.package = package
        else:
            file_descriptor_proto.name = proto_name + '.proto'

        descriptor_pool.Add(file_descriptor_proto)
        result = descriptor_pool.FindFileByName(file_descriptor_proto.name)

        if _USE_C_DESCRIPTORS:
            return result.message_types_by_name[desc_proto.name]

    full_message_name = [desc_proto.name]
    if package: full_message_name.insert(0, package)

    # Create Descriptors for enum types
    enum_types = {}
    for enum_proto in desc_proto.enum_type:
        full_name = '.'.join(full_message_name + [enum_proto.name])
        enum_desc = EnumDescriptor(enum_proto.name, full_name, None, [
            EnumValueDescriptor(enum_val.name, ii, enum_val.number)
            for ii, enum_val in enumerate(enum_proto.value)
        ])
        enum_types[full_name] = enum_desc

    # Create Descriptors for nested types
    nested_types = {}
    for nested_proto in desc_proto.nested_type:
        full_name = '.'.join(full_message_name + [nested_proto.name])
        # Nested types are just those defined inside of the message, not all types
        # used by fields in the message, so no loops are possible here.
        nested_desc = MakeClassDescriptor(descriptor_pool,
                                          nested_proto,
                                          package='.'.join(full_message_name),
                                          build_file_if_cpp=False,
                                          syntax=syntax)
        nested_types[full_name] = nested_desc

    fields = []
    for field_proto in desc_proto.field:
        full_name = '.'.join(full_message_name + [field_proto.name])
        enum_desc = None
        nested_desc = None
        if field_proto.json_name:
            json_name = field_proto.json_name
        else:
            json_name = None
        if field_proto.HasField('type_name'):
            type_name = field_proto.type_name
            full_type_name = '.'.join(full_message_name +
                                      [type_name[type_name.rfind('.') + 1:]])
            if full_type_name in nested_types:
                nested_desc = nested_types[full_type_name]
            elif full_type_name in enum_types:
                enum_desc = enum_types[full_type_name]
            # Else type_name references a non-local type, which isn't implemented
        field = FieldDescriptor(field_proto.name,
                                full_name,
                                field_proto.number - 1,
                                field_proto.number,
                                field_proto.type,
                                FieldDescriptor.ProtoTypeToCppProtoType(
                                    field_proto.type),
                                field_proto.label,
                                None,
                                nested_desc,
                                enum_desc,
                                None,
                                False,
                                None,
                                options=_OptionsOrNone(field_proto),
                                has_default_value=False,
                                json_name=json_name)
        fields.append(field)

    desc_name = '.'.join(full_message_name)
    return Descriptor(desc_proto.name,
                      desc_name,
                      None,
                      None,
                      fields,
                      list(nested_types.values()),
                      list(enum_types.values()), [],
                      options=_OptionsOrNone(desc_proto))