AllenNeuralDynamics / AllenNeuralDynamics/biodata-schema

HumanSubject species validator not working correctly with JSON/dictionary input

Abierto
#59 0 comentarios 0 reacciones 1 asignado Reclamado por @dbirman Ver en GitHub
Lenguaje dominante
Python
Estrellas
0
Forks
0
Métricas de merge de PR
Sin PR fusionados en 30 d

Descripción

**Describe the bug**
The `HumanSubject` validator that checks that the species field is human does not work properly when validating a model from dictionaries read in from a JSON file.

**To Reproduce**
```python
import json
from aind_data_schema.components.subjects import HumanSubject, Sex
from aind_data_schema_models.species import Species, SpeciesModel
from aind_data_schema_models.organizations import Organization

# Make a dictionary directly from the schema
my_human_dict = json.loads(Species.HUMAN.model_dump_json())

# Make a HumanSubject using Species.HUMAN -- works
HumanSubject.model_validate({
"species": Species.HUMAN,
"sex": "Male",
"year_of_birth": 1948,
"source": Organization.AI
})
# HumanSubject(object_type='Human subject', species=_Homo_Sapiens(name='Homo sapiens', common_name='Human', registry=, registry_identifier='NCBI:txid9606'), sex='Male', year_of_birth=1948, source=_Allen_Institute(name='Allen Institute', abbreviation='AI', registry=, registry_identifier='03cpe7c52'))

# Make a HumanSubject using the dictionary -- fails
HumanSubject.model_validate({
"species": my_human_dict,
"sex": "Male",
"year_of_birth": 1948,
"source": Organization.AI
})
# pydantic_core._pydantic_core.ValidationError: 1 validation error for HumanSubject
# species
# Value error, HumanSubject species must be HUMAN [type=value_error, input_value={'name': 'Homo sapiens', ...ifier': 'NCBI:txid9606'}, input_type=dict]
# For further information visit https://errors.pydantic.dev/2.11/v/value_error
```

**Expected behavior**
Should return a valid `HumanSubject`.

I was able to get a version of `HumanSubject` to work like this if I changed the `species` field to be `Species.ONE_OF` (like the other species-specific subject models) and change the `field_validator` parameter to `mode="after"`. But this does lose the default of `Species.HUMAN` --- not sure how to keep that. I did need to make both changes for it to work.

```python
from pydantic import Field, field_validator, model_validator
from aind_data_schema.base import DataModel

class MyHumanSubject(DataModel):
"""Description of a human subject that validates with a dictionary for Species"""

species: Species.ONE_OF = Field(..., title="species") # Changed from original SpeciesModel = Field(default=Species.HUMAN, title="Species")
sex: Sex = Field(..., title="Sex")
year_of_birth: int = Field(..., title="Year of birth")
source: Organization.ONE_OF = Field(
...,
description="Where the subject was acquired from.",
title="Source",
)

@field_validator("species", mode="after") # Mode changed from "before" in original
def validate_species_is_human(cls, v):
"""Ensure species is always human for HumanSubject"""
if v != Species.HUMAN:
raise ValueError("HumanSubject species must be HUMAN")
return v

# Make a HumanSubject using Species.HUMAN -- still works
MyHumanSubject.model_validate({
"species": Species.HUMAN,
"sex": "Male",
"year_of_birth": 1948,
"source": Organization.AI
})
# MyHumanSubject(object_type='My human subject', species=_Homo_Sapiens(name='Homo sapiens', common_name='Human', registry=, registry_identifier='NCBI:txid9606'), sex='Male', year_of_birth=1948, source=_Allen_Institute(name='Allen Institute', abbreviation='AI', registry=, registry_identifier='03cpe7c52'))

# Make a HumanSubject using the dictionary -- now works
MyHumanSubject.model_validate({
"species": my_human_dict,
"sex": "Male",
"year_of_birth": 1948,
"source": Organization.AI
})
# MyHumanSubject(object_type='My human subject', species=_Homo_Sapiens(name='Homo sapiens', common_name='Human', registry=, registry_identifier='NCBI:txid9606'), sex='Male', year_of_birth=1948, source=_Allen_Institute(name='Allen Institute', abbreviation='AI', registry=, registry_identifier='03cpe7c52'))

# Make a HumanSubject using the wrong species -- fails as expected
MyHumanSubject.model_validate({
"species": Species.RHESUS_MACAQUE,
"sex": "Male",
"year_of_birth": 1948,
"source": Organization.AI
})
# pydantic_core._pydantic_core.ValidationError: 1 validation error for MyHumanSubject
# species
# Value error, HumanSubject species must be HUMAN [type=value_error, input_value=_Macaca_Mulatta(name='Mac...ntifier='NCBI:txid9544'), input_type=_Macaca_Mulatta]
# For further information visit https://errors.pydantic.dev/2.11/v/value_error
```

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.