Remove `Optional` for `list` items.
- Dominant language
- Python
- Stars
- 7
- Forks
- 15
- PR merge metrics
- No merged PRs in 30d
Description
Stems from the UI observed issue/discussion between @candleindark @waxlamp and me
- https://github.com/dandi/dandi-archive/issues/2150
where we observe an ambiguity that schema allows for two semantically identical values of `null` (nothing) and `[]` (empty list) to be used.
We have about 30 unique attributes of such kind used in 34 definitions (overloads or whatever)
```shell
❯ grep 'Optional\[List' dandischema/models.py | sort | uniq -c | nl
1 1 affiliation: Optional[List[Affiliation]] = Field(
2 1 altName: Optional[List[Identifier]] = Field(
3 1 anatomy: Optional[List[Anatomy]] = Field(
4 2 approach: Optional[List[ApproachType]] = Field(
5 1 assayType: Optional[List[AssayType]] = Field(
6 1 contactPoint: Optional[List[ContactPoint]] = Field(
7 1 dataStandard: Optional[List[StandardsType]] = Field(
8 1 disorder: Optional[List[Disorder]] = Field(
9 1 dxdate: Optional[List[Union[date, datetime]]] = Field(
10 1 ethicsApproval: Optional[List[EthicsApproval]] = Field(
11 1 hasMember: Optional[List[Identifier]] = Field(
12 1 keywords: Optional[List[str]] = Field(
13 1 license: Optional[List[LicenseType]] = Field(
14 2 measurementTechnique: Optional[List[MeasurementTechniqueType]] = Field(
15 1 protocol: Optional[List[AnyHttpUrl]] = Field(
16 1 relatedParticipant: Optional[List[RelatedParticipant]] = Field(
17 1 relatedResource: Optional[List[Resource]] = Field(
18 1 roleName: Optional[List[RoleType]] = Field(
19 1 sameAs: Optional[List[AnyHttpUrl]] = Field(
20 2 sameAs: Optional[List[Identifier]] = Field(
21 1 species: Optional[List[SpeciesType]] = Field(
22 1 studyTarget: Optional[List[str]] = Field(
23 1 used: Optional[List[Equipment]] = Field(
24 1 variableMeasured: Optional[List[PropertyValue]] = Field(
25 1 variableMeasured: Optional[List[str]] = Field(
26 2 wasAttributedTo: Optional[List[Participant]] = Field(
27 1 wasDerivedFrom: Optional[List["BioSample"]] = Field(
28 1 wasDerivedFrom: Optional[List[BioSample]] = Field(
29 1 wasGeneratedBy: Optional[List["Session"]] = Field(
30 1 wasGeneratedBy: Optional[List[Union[Session, Project, Activity]]] = Field(
```
and all of them defaulting to `None`
```shell
❯ grep 'Optional\[List' -A 1 dandischema/models.py
dxdate: Optional[List[Union[date, datetime]]] = Field(
None,
--
roleName: Optional[List[RoleType]] = Field(
None,
--
contactPoint: Optional[List[ContactPoint]] = Field(
None,
--
affiliation: Optional[List[Affiliation]] = Field(
None,
--
dataStandard: Optional[List[StandardsType]] = Field(
None, json_schema_extra={"readOnly": True}
--
approach: Optional[List[ApproachType]] = Field(
None, json_schema_extra={"readOnly": True}
--
measurementTechnique: Optional[List[MeasurementTechniqueType]] = Field(
None, json_schema_extra={"readOnly": True, "nskey": "schema"}
--
variableMeasured: Optional[List[str]] = Field(
None, json_schema_extra={"readOnly": True, "nskey": "schema"}
--
species: Optional[List[SpeciesType]] = Field(
None, json_schema_extra={"readOnly": True}
--
used: Optional[List[Equipment]] = Field(
None,
--
wasGeneratedBy: Optional[List["Session"]] = Field(
None,
--
altName: Optional[List[Identifier]] = Field(
None, json_schema_extra={"nskey": "dandi"}
--
disorder: Optional[List[Disorder]] = Field(
None,
--
relatedParticipant: Optional[List[RelatedParticipant]] = Field(
None,
--
sameAs: Optional[List[Identifier]] = Field(
None,
--
assayType: Optional[List[AssayType]] = Field(
None,
--
anatomy: Optional[List[Anatomy]] = Field(
None,
--
wasDerivedFrom: Optional[List["BioSample"]] = Field(
None,
--
wasAttributedTo: Optional[List[Participant]] = Field(
None,
--
sameAs: Optional[List[Identifier]] = Field(
None, json_schema_extra={"nskey": "schema"}
--
hasMember: Optional[List[Identifier]] = Field(
None, json_schema_extra={"nskey": "prov"}
--
studyTarget: Optional[List[str]] = Field(
None,
--
license: Optional[List[LicenseType]] = Field(
None,
--
protocol: Optional[List[AnyHttpUrl]] = Field(
None,
--
ethicsApproval: Optional[List[EthicsApproval]] = Field(
None, title="Ethics approvals", json_schema_extra={"nskey": "dandi"}
--
keywords: Optional[List[str]] = Field(
None,
--
relatedResource: Optional[List[Resource]] = Field(
None, json_schema_extra={"nskey": "dandi"}
--
sameAs: Optional[List[AnyHttpUrl]] = Field(
None, json_schema_extra={"nskey": "schema"}
--
approach: Optional[List[ApproachType]] = Field(
None, json_schema_extra={"readOnly": True, "nskey": "dandi"}
--
measurementTechnique: Optional[List[MeasurementTechniqueType]] = Field(
None, json_schema_extra={"readOnly": True, "nskey": "schema"}
--
variableMeasured: Optional[List[PropertyValue]] = Field(
None, json_schema_extra={"readOnly": True, "nskey": "schema"}
--
wasDerivedFrom: Optional[List[BioSample]] = Field(
None, json_schema_extra={"nskey": "prov"}
--
wasAttributedTo: Optional[List[Participant]] = Field(
None,
--
wasGeneratedBy: Optional[List[Union[Session, Project, Activity]]] = Field(
None,
```
Why do not we drop `Optional` and just default to empty list there?
@satra wdyt?
- [x] @candleindark raised [concern](https://github.com/dandi/dandi-schema/issues/286#issuecomment-2667370844) that linkml would anyways convert into pydantic model as `Optional[List[]]` when multivalue slot is used.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.