Skip to content

Commit 3550bb2

Browse files
committed
more flexible type validation for prop value in I/O appmetadata
1 parent 48b30f1 commit 3550bb2

1 file changed

Lines changed: 26 additions & 4 deletions

File tree

clams/appmetadata/__init__.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import subprocess
44
import sys
55
from pathlib import Path
6-
from typing import Union, Dict, List, Optional, Literal
6+
from typing import Union, Dict, List, Optional, Literal, Any
77

88
import mmif
99
import pydantic
@@ -101,11 +101,33 @@ class Output(_BaseModel):
101101
"and also can be used as a expansion specification for the type definition beyond the base "
102102
"vocabulary."
103103
)
104-
properties: Dict[str, real_valued_primitives] = pydantic.Field(
105-
{},
106-
description="(optional) Specification for type properties, if any. ``\"*\"`` indicates any value."
104+
# TODO (krim @ 5/12/21): currently there's no way to validate the property
105+
# types based on vocabulary specification of an annotation type. As a result,
106+
# we allow "any" type and do some basic validation below, but we need a
107+
# better way for validation.
108+
properties: Dict[str, Any] = pydantic.Field(
109+
{},
110+
description="(optional) Specification for type properties, if any. `*` indicates any value."
107111
)
108112

113+
@pydantic.field_validator('properties', mode='before')
114+
@classmethod
115+
def validate_properties(cls, value):
116+
if not isinstance(value, dict):
117+
raise ValueError("Properties must be a dictionary.")
118+
for key, val in value.items():
119+
if not isinstance(key, str):
120+
raise ValueError(f"Property key '{key}' must be a string.")
121+
if isinstance(val, list):
122+
if not all(isinstance(item, type(val[0])) for item in val):
123+
raise ValueError(f"All elements in the list for key '{key}' must be of the same type.")
124+
elif isinstance(val, dict):
125+
if not all(isinstance(k, str) for k in val.keys()):
126+
raise ValueError(f"All keys in the dictionary for key '{key}' must be strings.")
127+
if not all(isinstance(v, type(next(iter(val.values())))) for v in val.values()):
128+
raise ValueError(f"All values in the dictionary for key '{key}' must be of the same type.")
129+
return value
130+
109131
def __init__(self, **kwargs):
110132
super().__init__(**kwargs)
111133

0 commit comments

Comments
 (0)