def testIsReference_withValidReferenceType_returnsTrue(self): """Test is_reference functionality on valid input.""" reference = datatypes_pb2.Reference() ref_descriptor_proto = self._descriptor_proto_for_descriptor( reference.DESCRIPTOR) self.assertTrue(annotation_utils.is_reference(reference)) self.assertTrue(annotation_utils.is_reference(reference.DESCRIPTOR)) self.assertTrue(annotation_utils.is_reference(ref_descriptor_proto))
def testIsReference_withInvalidReferenceType_returnsFalse(self): """Test is_reference functionality on invalid input.""" boolean = datatypes_pb2.Boolean() code = datatypes_pb2.Code() self.assertFalse(annotation_utils.is_reference(boolean)) self.assertFalse(annotation_utils.is_reference(boolean.DESCRIPTOR)) self.assertFalse(annotation_utils.is_reference(code)) self.assertFalse(annotation_utils.is_reference(code.DESCRIPTOR))
def _validate_field(msg: message.Message, field: descriptor.FieldDescriptor, field_name: str, primitive_handler_: primitive_handler.PrimitiveHandler): """Validates that required fields are set, and performs basic temporal checks. Args: msg: The Message that the field belongs to. field: The FieldDescriptor of the field to examine. field_name: The name of the field. primitive_handler_: Responsible for returning PrimitiveWrappers. Raises: fhir_errors.InvalidFhirError: In the event that a required field is not set or if temporal requirements are not met. """ if annotation_utils.field_is_required( field) and not proto_utils.field_is_set(msg, field): raise fhir_errors.InvalidFhirError( f'Required field `{field.full_name}` is missing.') if annotation_utils.is_reference(field.message_type): _validate_reference_field(msg, field) return if field.type == descriptor.FieldDescriptor.TYPE_MESSAGE: # Returns the first value only for a singular field for i in range(proto_utils.field_content_length(msg, field)): submessage = proto_utils.get_value_at_field_index(msg, field, i) _validate_fhir_constraints(submessage, field_name, primitive_handler_) # Run extra validation for some types, until FHIRPath validation covers # these as well if fhir_types.is_period(submessage): _validate_period(submessage, field_name)
def merge_value(self, json_value: Any, target: message.Message): """Merges the provided json_value into the target Message. Args: json_value: A Python-native representation of JSON data. target: The target Message to merge the JSON data into. """ target_descriptor = target.DESCRIPTOR if annotation_utils.is_primitive_type(target_descriptor): if isinstance(json_value, dict): # This is a primitive type extension. Merge the extension fields into # the empty target proto, and tag it as having no value. self._merge_message(json_value, target) extension_field = target_descriptor.fields_by_name.get( 'extension') if extension_field is None: raise ValueError( "Invalid primitive. No 'extension' field exists on " f"{target_descriptor.full_name}.") primitive_has_no_value = extensions.create_primitive_has_no_value( extension_field.message_type) proto_utils.append_value_at_field(target, extension_field, primitive_has_no_value) else: wrapper = self.primitive_handler.primitive_wrapper_from_json_value( json_value, type(target), default_timezone=self.default_timezone) wrapper.merge_into(target) elif annotation_utils.is_reference(target_descriptor): self._merge_message(json_value, target) references.split_if_relative_reference(target) else: if isinstance(json_value, dict): # The provided value must be another FHIR element self._merge_message(json_value, target) elif isinstance(json_value, (tuple, list)) and len(json_value) == 1: # Check if the target field is non-repeated, and we're trying to # populate it with a single-element array. This is considered valid, and # occurs when a profiled resource reduces the size of a repeated FHIR # field to a maximum of 1. self._merge_message(json_value[0], target) else: raise ValueError( 'Expected a JSON object for field of type: {}.'.format( target_descriptor.full_name))
def _print(self, msg: message.Message): """Prints the JSON representation of message to the underlying generator.""" # TODO: Identify ContainedResource with an annotation if msg.DESCRIPTOR.name == 'ContainedResource': self._print_contained_resource(msg) elif msg.DESCRIPTOR.full_name == any_pb2.Any.DESCRIPTOR.full_name: contained_resource = self.primitive_handler.new_contained_resource( ) cast(any_pb2.Any, msg).Unpack(contained_resource) self._print_contained_resource(contained_resource) elif fhir_types.is_extension(msg): self._print_extension(msg) elif annotation_utils.is_reference(msg): self._print_reference(msg) else: self._print_message(msg)
def _print(self, msg: message.Message) -> None: """Prints the JSON representation of message to the underlying generator.""" # TODO: Identify ContainedResource with an annotation if msg.DESCRIPTOR.name == 'ContainedResource': self._print_contained_resource(msg) elif msg.DESCRIPTOR.full_name == any_pb2.Any.DESCRIPTOR.full_name: contained_resource = self.primitive_handler.new_contained_resource( ) if not cast(any_pb2.Any, msg).Unpack(contained_resource): # If we can't unpack the Any, drop it. # TODO: Use a registry to determine the correct # ContainedResource to unpack to return self._print_contained_resource(contained_resource) elif fhir_types.is_extension(msg): self._print_extension(msg) elif annotation_utils.is_reference(msg): self._print_reference(msg) else: self._print_message(msg)
def _validate_reference(reference: message.Message): """Raises a ValueError if the provided Message is not a FHIR reference.""" if not annotation_utils.is_reference(reference): raise ValueError( f'Message {reference.DESCRIPTOR.name} is not a FHIR reference.')