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)}')
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() }
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
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
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}, }
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
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))
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))
def model_to_swagger(model: BaseModel, indent: int = 2): return json.dumps(model.schema(), indent=indent)