def validate_derived_values_not_in_source_config(entity_type: BaseModel, entity_source_config: Entity):
    derived_properties = set([name for (name, prop) in entity_type.schema()['properties'].items()
                              if 'derived' in prop and prop['derived'] is True])
    attribute_names = set([attr.name for attr in entity_source_config.attributes])
    intersection = derived_properties.intersection(attribute_names)
    if intersection:
        raise DataException(f'Derived value fields not allowed in source files: {", ".join(intersection)}')
Пример #2
0
def get_model_defaults(model_class: BaseModel):
    """Return the default values for fields in a Pydantic BaseModel.
    If a field doesn't have a default then return None.
    Default values may also be None.

    Returns
    -------
    dict

    """
    return {
        x: y.get("default")
        for x, y in model_class.schema()["properties"].items()
    }
Пример #3
0
    def get_ref_entity_name_to_ref_field_value(
            self, entity: BaseModel,
            entity_type: Type[BaseModel]) -> Dict[str, str]:
        """
        Get a dictionary with name of reference entities to value of the referencing field,
        being id of the referencing entity
        :param entity: CSR entity
        :param entity_type: type of the entity
        :return: dictionary from reference entity name to value of reference field
        """
        entity_ref_to_ref_id = dict()
        id_attribute = self.get_id_field_name(entity_type)
        entity_type_name = entity_type.schema()['title']
        entity_id = entity.__getattribute__(id_attribute)
        entity_ref_to_ref_id[entity_type_name] = entity_id

        if entity_type_name == 'Individual':
            return entity_ref_to_ref_id

        # Follow reference fields to obtain identifiers of linked entities
        ref_fields = self.get_field_properties_by_keyword(
            entity_type, 'references')
        for field_name, ref_entity_name in ref_fields.items():
            if not self.skip_reference(type(entity), ref_entity_name):
                # Lookup referenced entity
                referenced_entity_type = list([
                    entity for entity in SubjectEntity.__args__
                    if entity.schema()['title'] == ref_entity_name
                ])[0]
                referenced_id = entity.__getattribute__(field_name)
                if not referenced_id:
                    continue
                referenced_id_attribute = self.get_id_field_name(
                    referenced_entity_type)
                referenced_entities = [
                    e
                    for e in self.subject_registry.entity_data[ref_entity_name]
                    if e.__getattribute__(referenced_id_attribute) ==
                    referenced_id
                ]
                if not referenced_entities:
                    raise MappingException(
                        f'{entity_type_name} with id {entity_id} has reference to non-existing'
                        f' {ref_entity_name} with id {referenced_id}.')
                # Recursively add identifiers from referenced entity
                referenced_ids = self.get_ref_entity_name_to_ref_field_value(
                    referenced_entities[0], referenced_entity_type)
                entity_ref_to_ref_id.update(referenced_ids)

        return entity_ref_to_ref_id
Пример #4
0
def gen_args_from_validator(prefix, validator: BaseModel):
    print(type(validator))
    schema = validator.schema()
    debug(schema)
    fields = {
        k: transform_validator_field(field_name=k,
                                     field_schema=v,
                                     required=True)
        for k, v in schema["properties"].items()
    }
    input_type_cls = type(
        f"{prefix}",
        (gr.InputObjectType, ),
        fields,
    )
    return input_type_cls
Пример #5
0
def schema_request_body(body: BaseModel = None) -> Optional[Dict[str, Any]]:
    if body is None:
        return None

    _schema = {"schema": replace_definitions(body.schema())}

    for field in body.__fields__.values():
        if issubclass(field.type_, File):
            return {
                "required": True,
                "content": {"multipart/form-data": _schema},
            }

    return {
        "required": True,
        "content": {"application/json": _schema},
    }
Пример #6
0
def create_random_model_dict(model: BaseModel,
                             can_fail: bool = True) -> Dict[str, Any]:
    def random_string(nchars: int) -> str:
        letters = [l for l in string.ascii_letters]
        return "".join([numpy.random.choice(letters) for i in range(nchars)])

    schema = model.schema()
    reqds = schema["required"]
    props = schema["properties"]
    optionalprops = list(set(props.keys()) - set(reqds))

    extras: List = []
    if can_fail:  # pragma: no cover
        if len(optionalprops) > 1:
            extras = [numpy.random.choice(optionalprops)]
        elif numpy.random.random() > 0.5:
            extras = optionalprops
    else:
        extras = optionalprops

    keys_subset = reqds + extras

    dct = {}
    for k in keys_subset:  # pragma: no cover
        v = props[k]
        value: Any = None

        if v.get("default") is not None:
            value = v["default"]
        elif v["type"] == "string":
            value = random_string(12)
        elif v["type"] == "boolean":
            value = numpy.random.choice([True, False])
        elif v["type"] == "number":
            value = numpy.random.random() * 1000

        dct[k] = value

    return dct
Пример #7
0
 def map_observation(self, entity: BaseModel, entity_id: str,
                     entity_type_to_id: Dict[str, str]):
     """
     Map entity to transmart-loader Observation
     :param entity: CSR entity
     :param entity_id: id of the entity
     :param entity_type_to_id: dictionary from entity type to id of the entity
     :return:
     """
     entity_fields = entity.__fields__.keys()
     entity_name = entity.schema()['title']
     individual_id = entity_type_to_id.pop('Individual', None)
     patient = self.individual_id_to_patient.get(individual_id, None)
     if not patient:
         raise MappingException(
             'No patient with identifier: {}. '
             'Failed to create observation for {} with id: {}. Entity {}, Ind {}'
             .format(individual_id,
                     type(entity).__name__, entity_id, entity,
                     self.individual_id_to_patient.keys()))
     for entity_field in entity_fields:
         concept_code = '{}.{}'.format(entity_name, entity_field)
         concept = self.concept_code_to_concept.get(concept_code)
         if concept is not None:
             if isinstance(entity, Individual) or not entity_type_to_id:
                 metadata = None
             else:
                 metadata = self.map_observation_metadata(entity_type_to_id)
             entity_value = getattr(entity, entity_field)
             if entity_value is not None:
                 if isinstance(entity_value, List):
                     for v in entity_value:
                         self.observations.append(
                             self.get_observation_for_value(
                                 v, concept, metadata, patient))
                 else:
                     self.observations.append(
                         self.get_observation_for_value(
                             entity_value, concept, metadata, patient))
Пример #8
0
    def _render_single_output(self, streamlit: st, output_data: BaseModel) -> None:
        try:
            if has_output_ui_renderer(output_data):
                if function_has_named_arg(output_data.render_output_ui, "input"):  # type: ignore
                    # render method also requests the input data
                    output_data.render_output_ui(streamlit, input=self._input_data)  # type: ignore
                else:
                    output_data.render_output_ui(streamlit)  # type: ignore
                return
        except Exception:
            # Use default auto-generation methods if the custom rendering throws an exception
            logger.exception(
                "Failed to execute custom render_output_ui function. Using auto-generation instead"
            )

        model_schema = output_data.schema(by_alias=False)
        model_properties = model_schema.get("properties")
        definitions = model_schema.get("definitions")

        if model_properties:
            for property_key in output_data.__dict__:
                property_schema = model_properties.get(property_key)
                if not property_schema.get("title"):
                    # Set property key as fallback title
                    property_schema["title"] = property_key

                output_property_value = output_data.__dict__[property_key]

                if has_output_ui_renderer(output_property_value):
                    output_property_value.render_output_ui(streamlit)  # type: ignore
                    continue

                if isinstance(output_property_value, BaseModel):
                    # Render output recursivly
                    streamlit.subheader(property_schema.get("title"))
                    if property_schema.get("description"):
                        streamlit.markdown(property_schema.get("description"))
                    self._render_single_output(streamlit, output_property_value)
                    continue

                if property_schema:
                    if schema_utils.is_single_file_property(property_schema):
                        self._render_single_file_property(
                            streamlit, property_schema, output_property_value
                        )
                        continue

                    if (
                        schema_utils.is_single_string_property(property_schema)
                        or schema_utils.is_single_number_property(property_schema)
                        or schema_utils.is_single_datetime_property(property_schema)
                        or schema_utils.is_single_boolean_property(property_schema)
                    ):
                        self._render_single_text_property(
                            streamlit, property_schema, output_property_value
                        )
                        continue
                    if definitions and schema_utils.is_single_enum_property(
                        property_schema, definitions
                    ):
                        self._render_single_text_property(
                            streamlit, property_schema, output_property_value.value
                        )
                        continue

                    # TODO: render dict as table

                    self._render_single_complex_property(
                        streamlit, property_schema, output_property_value
                    )
            return

        # Display single field in code block:
        # if len(output_data.__dict__) == 1:
        #     value = next(iter(output_data.__dict__.values()))

        #     if type(value) in (int, float, str):
        #         # Should not be a complex object (with __dict__) -> should be a primitive
        #         # hasattr(output_data.__dict__[0], '__dict__')
        #         streamlit.subheader("This is a test:")
        #         streamlit.code(value, language="plain")
        #         return

        # Fallback to json output
        streamlit.json(jsonable_encoder(output_data))
Пример #9
0
 def model_to_swagger(model: BaseModel, indent: int = 2):
     return json.dumps(model.schema(), indent=indent)