AllenNeuralDynamics / AllenNeuralDynamics/biodata-schema
HumanSubject species validator not working correctly with JSON/dictionary input
- 主要言語
- Python
- スター
- 0
- フォーク
- 0
- PR マージ指標
- 30日以内にマージされた PR はありません
説明
**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
```
コントリビューションガイド
評価
この issue はまだ評価されていません。