예제 #1
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})")
예제 #2
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
예제 #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 _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
예제 #5
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
예제 #6
0
 def _field_options(self, field: FieldDescriptor, provider: FieldDescriptor = None):
     provider = provider or self._BREWBLOX_PROVIDER
     return field.GetOptions().Extensions[provider]