From d61d1ecf2272d3a883b8bd6b5b29c5830e836917 Mon Sep 17 00:00:00 2001 From: sneakers-the-rat Date: Tue, 13 Aug 2024 23:39:11 -0700 Subject: [PATCH] regenerate models --- .../hdmf_common/v1_1_0/hdmf_common_table.py | 43 +++++++++++-------- .../hdmf_common/v1_1_2/hdmf_common_table.py | 43 +++++++++++-------- .../hdmf_common/v1_1_3/hdmf_common_table.py | 43 +++++++++++-------- .../hdmf_common/v1_2_0/hdmf_common_table.py | 43 +++++++++++-------- .../hdmf_common/v1_2_1/hdmf_common_table.py | 43 +++++++++++-------- .../hdmf_common/v1_3_0/hdmf_common_table.py | 43 +++++++++++-------- .../hdmf_common/v1_4_0/hdmf_common_table.py | 43 +++++++++++-------- .../hdmf_common/v1_5_0/hdmf_common_table.py | 43 +++++++++++-------- .../hdmf_common/v1_5_1/hdmf_common_table.py | 43 +++++++++++-------- .../hdmf_common/v1_6_0/hdmf_common_table.py | 43 +++++++++++-------- .../hdmf_common/v1_7_0/hdmf_common_table.py | 43 +++++++++++-------- .../hdmf_common/v1_8_0/hdmf_common_table.py | 43 +++++++++++-------- 12 files changed, 300 insertions(+), 216 deletions(-) diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_0/hdmf_common_table.py index 4676d58..e37cea0 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_0/hdmf_common_table.py @@ -245,7 +245,7 @@ class DynamicTableMixin(BaseModel): """ model_config = ConfigDict(extra="allow") - __pydantic_extra__: Dict[str, Union[list, "NDArray", "VectorDataMixin"]] + __pydantic_extra__: Dict[str, Union["VectorDataMixin", "VectorIndexMixin", "NDArray", list]] NON_COLUMN_FIELDS: ClassVar[tuple[str]] = ( "name", "colnames", @@ -445,8 +445,9 @@ class DynamicTableMixin(BaseModel): model["colnames"] = colnames return model - @model_validator(mode="after") - def cast_extra_columns(self) -> "DynamicTableMixin": + @model_validator(mode="before") + @classmethod + def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict: """ If extra columns are passed as just lists or arrays, cast to VectorData before we resolve targets for VectorData and VectorIndex pairs. @@ -454,22 +455,20 @@ class DynamicTableMixin(BaseModel): See :meth:`.cast_specified_columns` for handling columns in the class specification """ # if columns are not in the specification, cast to a generic VectorData - for key, val in self.__pydantic_extra__.items(): + for key, val in model.items(): + if key in cls.model_fields: + continue if not isinstance(val, (VectorData, VectorIndex)): try: if key.endswith("_index"): - self.__pydantic_extra__[key] = VectorIndex( - name=key, description="", value=val - ) + model[key] = VectorIndex(name=key, description="", value=val) else: - self.__pydantic_extra__[key] = VectorData( - name=key, description="", value=val - ) + model[key] = VectorData(name=key, description="", value=val) except ValidationError as e: raise ValidationError( f"field {key} cannot be cast to VectorData from {val}" ) from e - return self + return model @model_validator(mode="after") def resolve_targets(self) -> "DynamicTableMixin": @@ -481,6 +480,8 @@ class DynamicTableMixin(BaseModel): # find an index idx = None for field_name in self.model_fields_set: + if field_name in self.NON_COLUMN_FIELDS or field_name == key: + continue # implicit name-based index field = getattr(self, field_name) if isinstance(field, VectorIndex) and ( @@ -519,17 +520,23 @@ class DynamicTableMixin(BaseModel): """ try: return handler(val) - except ValidationError: + except ValidationError as e: annotation = cls.model_fields[info.field_name].annotation if type(annotation).__name__ == "_UnionGenericAlias": annotation = annotation.__args__[0] - return handler( - annotation( - val, - name=info.field_name, - description=cls.model_fields[info.field_name].description, + try: + # should pass if we're supposed to be a VectorData column + # don't want to override intention here by insisting that it is + # *actually* a VectorData column in case an NDArray has been specified for now + return handler( + annotation( + val, + name=info.field_name, + description=cls.model_fields[info.field_name].description, + ) ) - ) + except Exception: + raise e class AlignedDynamicTableMixin(DynamicTableMixin): diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_2/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_2/hdmf_common_table.py index 5066800..128e62f 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_2/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_2/hdmf_common_table.py @@ -245,7 +245,7 @@ class DynamicTableMixin(BaseModel): """ model_config = ConfigDict(extra="allow") - __pydantic_extra__: Dict[str, Union[list, "NDArray", "VectorDataMixin"]] + __pydantic_extra__: Dict[str, Union["VectorDataMixin", "VectorIndexMixin", "NDArray", list]] NON_COLUMN_FIELDS: ClassVar[tuple[str]] = ( "name", "colnames", @@ -445,8 +445,9 @@ class DynamicTableMixin(BaseModel): model["colnames"] = colnames return model - @model_validator(mode="after") - def cast_extra_columns(self) -> "DynamicTableMixin": + @model_validator(mode="before") + @classmethod + def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict: """ If extra columns are passed as just lists or arrays, cast to VectorData before we resolve targets for VectorData and VectorIndex pairs. @@ -454,22 +455,20 @@ class DynamicTableMixin(BaseModel): See :meth:`.cast_specified_columns` for handling columns in the class specification """ # if columns are not in the specification, cast to a generic VectorData - for key, val in self.__pydantic_extra__.items(): + for key, val in model.items(): + if key in cls.model_fields: + continue if not isinstance(val, (VectorData, VectorIndex)): try: if key.endswith("_index"): - self.__pydantic_extra__[key] = VectorIndex( - name=key, description="", value=val - ) + model[key] = VectorIndex(name=key, description="", value=val) else: - self.__pydantic_extra__[key] = VectorData( - name=key, description="", value=val - ) + model[key] = VectorData(name=key, description="", value=val) except ValidationError as e: raise ValidationError( f"field {key} cannot be cast to VectorData from {val}" ) from e - return self + return model @model_validator(mode="after") def resolve_targets(self) -> "DynamicTableMixin": @@ -481,6 +480,8 @@ class DynamicTableMixin(BaseModel): # find an index idx = None for field_name in self.model_fields_set: + if field_name in self.NON_COLUMN_FIELDS or field_name == key: + continue # implicit name-based index field = getattr(self, field_name) if isinstance(field, VectorIndex) and ( @@ -519,17 +520,23 @@ class DynamicTableMixin(BaseModel): """ try: return handler(val) - except ValidationError: + except ValidationError as e: annotation = cls.model_fields[info.field_name].annotation if type(annotation).__name__ == "_UnionGenericAlias": annotation = annotation.__args__[0] - return handler( - annotation( - val, - name=info.field_name, - description=cls.model_fields[info.field_name].description, + try: + # should pass if we're supposed to be a VectorData column + # don't want to override intention here by insisting that it is + # *actually* a VectorData column in case an NDArray has been specified for now + return handler( + annotation( + val, + name=info.field_name, + description=cls.model_fields[info.field_name].description, + ) ) - ) + except Exception: + raise e class AlignedDynamicTableMixin(DynamicTableMixin): diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_3/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_3/hdmf_common_table.py index 02d0686..12b84b1 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_3/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_1_3/hdmf_common_table.py @@ -245,7 +245,7 @@ class DynamicTableMixin(BaseModel): """ model_config = ConfigDict(extra="allow") - __pydantic_extra__: Dict[str, Union[list, "NDArray", "VectorDataMixin"]] + __pydantic_extra__: Dict[str, Union["VectorDataMixin", "VectorIndexMixin", "NDArray", list]] NON_COLUMN_FIELDS: ClassVar[tuple[str]] = ( "name", "colnames", @@ -445,8 +445,9 @@ class DynamicTableMixin(BaseModel): model["colnames"] = colnames return model - @model_validator(mode="after") - def cast_extra_columns(self) -> "DynamicTableMixin": + @model_validator(mode="before") + @classmethod + def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict: """ If extra columns are passed as just lists or arrays, cast to VectorData before we resolve targets for VectorData and VectorIndex pairs. @@ -454,22 +455,20 @@ class DynamicTableMixin(BaseModel): See :meth:`.cast_specified_columns` for handling columns in the class specification """ # if columns are not in the specification, cast to a generic VectorData - for key, val in self.__pydantic_extra__.items(): + for key, val in model.items(): + if key in cls.model_fields: + continue if not isinstance(val, (VectorData, VectorIndex)): try: if key.endswith("_index"): - self.__pydantic_extra__[key] = VectorIndex( - name=key, description="", value=val - ) + model[key] = VectorIndex(name=key, description="", value=val) else: - self.__pydantic_extra__[key] = VectorData( - name=key, description="", value=val - ) + model[key] = VectorData(name=key, description="", value=val) except ValidationError as e: raise ValidationError( f"field {key} cannot be cast to VectorData from {val}" ) from e - return self + return model @model_validator(mode="after") def resolve_targets(self) -> "DynamicTableMixin": @@ -481,6 +480,8 @@ class DynamicTableMixin(BaseModel): # find an index idx = None for field_name in self.model_fields_set: + if field_name in self.NON_COLUMN_FIELDS or field_name == key: + continue # implicit name-based index field = getattr(self, field_name) if isinstance(field, VectorIndex) and ( @@ -519,17 +520,23 @@ class DynamicTableMixin(BaseModel): """ try: return handler(val) - except ValidationError: + except ValidationError as e: annotation = cls.model_fields[info.field_name].annotation if type(annotation).__name__ == "_UnionGenericAlias": annotation = annotation.__args__[0] - return handler( - annotation( - val, - name=info.field_name, - description=cls.model_fields[info.field_name].description, + try: + # should pass if we're supposed to be a VectorData column + # don't want to override intention here by insisting that it is + # *actually* a VectorData column in case an NDArray has been specified for now + return handler( + annotation( + val, + name=info.field_name, + description=cls.model_fields[info.field_name].description, + ) ) - ) + except Exception: + raise e class AlignedDynamicTableMixin(DynamicTableMixin): diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_0/hdmf_common_table.py index 2d3ccc4..9c99479 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_0/hdmf_common_table.py @@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel): """ model_config = ConfigDict(extra="allow") - __pydantic_extra__: Dict[str, Union[list, "NDArray", "VectorDataMixin"]] + __pydantic_extra__: Dict[str, Union["VectorDataMixin", "VectorIndexMixin", "NDArray", list]] NON_COLUMN_FIELDS: ClassVar[tuple[str]] = ( "name", "colnames", @@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel): model["colnames"] = colnames return model - @model_validator(mode="after") - def cast_extra_columns(self) -> "DynamicTableMixin": + @model_validator(mode="before") + @classmethod + def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict: """ If extra columns are passed as just lists or arrays, cast to VectorData before we resolve targets for VectorData and VectorIndex pairs. @@ -455,22 +456,20 @@ class DynamicTableMixin(BaseModel): See :meth:`.cast_specified_columns` for handling columns in the class specification """ # if columns are not in the specification, cast to a generic VectorData - for key, val in self.__pydantic_extra__.items(): + for key, val in model.items(): + if key in cls.model_fields: + continue if not isinstance(val, (VectorData, VectorIndex)): try: if key.endswith("_index"): - self.__pydantic_extra__[key] = VectorIndex( - name=key, description="", value=val - ) + model[key] = VectorIndex(name=key, description="", value=val) else: - self.__pydantic_extra__[key] = VectorData( - name=key, description="", value=val - ) + model[key] = VectorData(name=key, description="", value=val) except ValidationError as e: raise ValidationError( f"field {key} cannot be cast to VectorData from {val}" ) from e - return self + return model @model_validator(mode="after") def resolve_targets(self) -> "DynamicTableMixin": @@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel): # find an index idx = None for field_name in self.model_fields_set: + if field_name in self.NON_COLUMN_FIELDS or field_name == key: + continue # implicit name-based index field = getattr(self, field_name) if isinstance(field, VectorIndex) and ( @@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel): """ try: return handler(val) - except ValidationError: + except ValidationError as e: annotation = cls.model_fields[info.field_name].annotation if type(annotation).__name__ == "_UnionGenericAlias": annotation = annotation.__args__[0] - return handler( - annotation( - val, - name=info.field_name, - description=cls.model_fields[info.field_name].description, + try: + # should pass if we're supposed to be a VectorData column + # don't want to override intention here by insisting that it is + # *actually* a VectorData column in case an NDArray has been specified for now + return handler( + annotation( + val, + name=info.field_name, + description=cls.model_fields[info.field_name].description, + ) ) - ) + except Exception: + raise e class AlignedDynamicTableMixin(DynamicTableMixin): diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_1/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_1/hdmf_common_table.py index df0d847..b487609 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_1/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_2_1/hdmf_common_table.py @@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel): """ model_config = ConfigDict(extra="allow") - __pydantic_extra__: Dict[str, Union[list, "NDArray", "VectorDataMixin"]] + __pydantic_extra__: Dict[str, Union["VectorDataMixin", "VectorIndexMixin", "NDArray", list]] NON_COLUMN_FIELDS: ClassVar[tuple[str]] = ( "name", "colnames", @@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel): model["colnames"] = colnames return model - @model_validator(mode="after") - def cast_extra_columns(self) -> "DynamicTableMixin": + @model_validator(mode="before") + @classmethod + def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict: """ If extra columns are passed as just lists or arrays, cast to VectorData before we resolve targets for VectorData and VectorIndex pairs. @@ -455,22 +456,20 @@ class DynamicTableMixin(BaseModel): See :meth:`.cast_specified_columns` for handling columns in the class specification """ # if columns are not in the specification, cast to a generic VectorData - for key, val in self.__pydantic_extra__.items(): + for key, val in model.items(): + if key in cls.model_fields: + continue if not isinstance(val, (VectorData, VectorIndex)): try: if key.endswith("_index"): - self.__pydantic_extra__[key] = VectorIndex( - name=key, description="", value=val - ) + model[key] = VectorIndex(name=key, description="", value=val) else: - self.__pydantic_extra__[key] = VectorData( - name=key, description="", value=val - ) + model[key] = VectorData(name=key, description="", value=val) except ValidationError as e: raise ValidationError( f"field {key} cannot be cast to VectorData from {val}" ) from e - return self + return model @model_validator(mode="after") def resolve_targets(self) -> "DynamicTableMixin": @@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel): # find an index idx = None for field_name in self.model_fields_set: + if field_name in self.NON_COLUMN_FIELDS or field_name == key: + continue # implicit name-based index field = getattr(self, field_name) if isinstance(field, VectorIndex) and ( @@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel): """ try: return handler(val) - except ValidationError: + except ValidationError as e: annotation = cls.model_fields[info.field_name].annotation if type(annotation).__name__ == "_UnionGenericAlias": annotation = annotation.__args__[0] - return handler( - annotation( - val, - name=info.field_name, - description=cls.model_fields[info.field_name].description, + try: + # should pass if we're supposed to be a VectorData column + # don't want to override intention here by insisting that it is + # *actually* a VectorData column in case an NDArray has been specified for now + return handler( + annotation( + val, + name=info.field_name, + description=cls.model_fields[info.field_name].description, + ) ) - ) + except Exception: + raise e class AlignedDynamicTableMixin(DynamicTableMixin): diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_3_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_3_0/hdmf_common_table.py index 7d465e2..14214b5 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_3_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_3_0/hdmf_common_table.py @@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel): """ model_config = ConfigDict(extra="allow") - __pydantic_extra__: Dict[str, Union[list, "NDArray", "VectorDataMixin"]] + __pydantic_extra__: Dict[str, Union["VectorDataMixin", "VectorIndexMixin", "NDArray", list]] NON_COLUMN_FIELDS: ClassVar[tuple[str]] = ( "name", "colnames", @@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel): model["colnames"] = colnames return model - @model_validator(mode="after") - def cast_extra_columns(self) -> "DynamicTableMixin": + @model_validator(mode="before") + @classmethod + def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict: """ If extra columns are passed as just lists or arrays, cast to VectorData before we resolve targets for VectorData and VectorIndex pairs. @@ -455,22 +456,20 @@ class DynamicTableMixin(BaseModel): See :meth:`.cast_specified_columns` for handling columns in the class specification """ # if columns are not in the specification, cast to a generic VectorData - for key, val in self.__pydantic_extra__.items(): + for key, val in model.items(): + if key in cls.model_fields: + continue if not isinstance(val, (VectorData, VectorIndex)): try: if key.endswith("_index"): - self.__pydantic_extra__[key] = VectorIndex( - name=key, description="", value=val - ) + model[key] = VectorIndex(name=key, description="", value=val) else: - self.__pydantic_extra__[key] = VectorData( - name=key, description="", value=val - ) + model[key] = VectorData(name=key, description="", value=val) except ValidationError as e: raise ValidationError( f"field {key} cannot be cast to VectorData from {val}" ) from e - return self + return model @model_validator(mode="after") def resolve_targets(self) -> "DynamicTableMixin": @@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel): # find an index idx = None for field_name in self.model_fields_set: + if field_name in self.NON_COLUMN_FIELDS or field_name == key: + continue # implicit name-based index field = getattr(self, field_name) if isinstance(field, VectorIndex) and ( @@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel): """ try: return handler(val) - except ValidationError: + except ValidationError as e: annotation = cls.model_fields[info.field_name].annotation if type(annotation).__name__ == "_UnionGenericAlias": annotation = annotation.__args__[0] - return handler( - annotation( - val, - name=info.field_name, - description=cls.model_fields[info.field_name].description, + try: + # should pass if we're supposed to be a VectorData column + # don't want to override intention here by insisting that it is + # *actually* a VectorData column in case an NDArray has been specified for now + return handler( + annotation( + val, + name=info.field_name, + description=cls.model_fields[info.field_name].description, + ) ) - ) + except Exception: + raise e class AlignedDynamicTableMixin(DynamicTableMixin): diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_4_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_4_0/hdmf_common_table.py index 47400e6..f79660e 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_4_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_4_0/hdmf_common_table.py @@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel): """ model_config = ConfigDict(extra="allow") - __pydantic_extra__: Dict[str, Union[list, "NDArray", "VectorDataMixin"]] + __pydantic_extra__: Dict[str, Union["VectorDataMixin", "VectorIndexMixin", "NDArray", list]] NON_COLUMN_FIELDS: ClassVar[tuple[str]] = ( "name", "colnames", @@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel): model["colnames"] = colnames return model - @model_validator(mode="after") - def cast_extra_columns(self) -> "DynamicTableMixin": + @model_validator(mode="before") + @classmethod + def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict: """ If extra columns are passed as just lists or arrays, cast to VectorData before we resolve targets for VectorData and VectorIndex pairs. @@ -455,22 +456,20 @@ class DynamicTableMixin(BaseModel): See :meth:`.cast_specified_columns` for handling columns in the class specification """ # if columns are not in the specification, cast to a generic VectorData - for key, val in self.__pydantic_extra__.items(): + for key, val in model.items(): + if key in cls.model_fields: + continue if not isinstance(val, (VectorData, VectorIndex)): try: if key.endswith("_index"): - self.__pydantic_extra__[key] = VectorIndex( - name=key, description="", value=val - ) + model[key] = VectorIndex(name=key, description="", value=val) else: - self.__pydantic_extra__[key] = VectorData( - name=key, description="", value=val - ) + model[key] = VectorData(name=key, description="", value=val) except ValidationError as e: raise ValidationError( f"field {key} cannot be cast to VectorData from {val}" ) from e - return self + return model @model_validator(mode="after") def resolve_targets(self) -> "DynamicTableMixin": @@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel): # find an index idx = None for field_name in self.model_fields_set: + if field_name in self.NON_COLUMN_FIELDS or field_name == key: + continue # implicit name-based index field = getattr(self, field_name) if isinstance(field, VectorIndex) and ( @@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel): """ try: return handler(val) - except ValidationError: + except ValidationError as e: annotation = cls.model_fields[info.field_name].annotation if type(annotation).__name__ == "_UnionGenericAlias": annotation = annotation.__args__[0] - return handler( - annotation( - val, - name=info.field_name, - description=cls.model_fields[info.field_name].description, + try: + # should pass if we're supposed to be a VectorData column + # don't want to override intention here by insisting that it is + # *actually* a VectorData column in case an NDArray has been specified for now + return handler( + annotation( + val, + name=info.field_name, + description=cls.model_fields[info.field_name].description, + ) ) - ) + except Exception: + raise e class AlignedDynamicTableMixin(DynamicTableMixin): diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_0/hdmf_common_table.py index 92c5eeb..6f6d0b0 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_0/hdmf_common_table.py @@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel): """ model_config = ConfigDict(extra="allow") - __pydantic_extra__: Dict[str, Union[list, "NDArray", "VectorDataMixin"]] + __pydantic_extra__: Dict[str, Union["VectorDataMixin", "VectorIndexMixin", "NDArray", list]] NON_COLUMN_FIELDS: ClassVar[tuple[str]] = ( "name", "colnames", @@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel): model["colnames"] = colnames return model - @model_validator(mode="after") - def cast_extra_columns(self) -> "DynamicTableMixin": + @model_validator(mode="before") + @classmethod + def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict: """ If extra columns are passed as just lists or arrays, cast to VectorData before we resolve targets for VectorData and VectorIndex pairs. @@ -455,22 +456,20 @@ class DynamicTableMixin(BaseModel): See :meth:`.cast_specified_columns` for handling columns in the class specification """ # if columns are not in the specification, cast to a generic VectorData - for key, val in self.__pydantic_extra__.items(): + for key, val in model.items(): + if key in cls.model_fields: + continue if not isinstance(val, (VectorData, VectorIndex)): try: if key.endswith("_index"): - self.__pydantic_extra__[key] = VectorIndex( - name=key, description="", value=val - ) + model[key] = VectorIndex(name=key, description="", value=val) else: - self.__pydantic_extra__[key] = VectorData( - name=key, description="", value=val - ) + model[key] = VectorData(name=key, description="", value=val) except ValidationError as e: raise ValidationError( f"field {key} cannot be cast to VectorData from {val}" ) from e - return self + return model @model_validator(mode="after") def resolve_targets(self) -> "DynamicTableMixin": @@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel): # find an index idx = None for field_name in self.model_fields_set: + if field_name in self.NON_COLUMN_FIELDS or field_name == key: + continue # implicit name-based index field = getattr(self, field_name) if isinstance(field, VectorIndex) and ( @@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel): """ try: return handler(val) - except ValidationError: + except ValidationError as e: annotation = cls.model_fields[info.field_name].annotation if type(annotation).__name__ == "_UnionGenericAlias": annotation = annotation.__args__[0] - return handler( - annotation( - val, - name=info.field_name, - description=cls.model_fields[info.field_name].description, + try: + # should pass if we're supposed to be a VectorData column + # don't want to override intention here by insisting that it is + # *actually* a VectorData column in case an NDArray has been specified for now + return handler( + annotation( + val, + name=info.field_name, + description=cls.model_fields[info.field_name].description, + ) ) - ) + except Exception: + raise e class AlignedDynamicTableMixin(DynamicTableMixin): diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_1/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_1/hdmf_common_table.py index 755b884..3590de9 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_1/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_5_1/hdmf_common_table.py @@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel): """ model_config = ConfigDict(extra="allow") - __pydantic_extra__: Dict[str, Union[list, "NDArray", "VectorDataMixin"]] + __pydantic_extra__: Dict[str, Union["VectorDataMixin", "VectorIndexMixin", "NDArray", list]] NON_COLUMN_FIELDS: ClassVar[tuple[str]] = ( "name", "colnames", @@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel): model["colnames"] = colnames return model - @model_validator(mode="after") - def cast_extra_columns(self) -> "DynamicTableMixin": + @model_validator(mode="before") + @classmethod + def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict: """ If extra columns are passed as just lists or arrays, cast to VectorData before we resolve targets for VectorData and VectorIndex pairs. @@ -455,22 +456,20 @@ class DynamicTableMixin(BaseModel): See :meth:`.cast_specified_columns` for handling columns in the class specification """ # if columns are not in the specification, cast to a generic VectorData - for key, val in self.__pydantic_extra__.items(): + for key, val in model.items(): + if key in cls.model_fields: + continue if not isinstance(val, (VectorData, VectorIndex)): try: if key.endswith("_index"): - self.__pydantic_extra__[key] = VectorIndex( - name=key, description="", value=val - ) + model[key] = VectorIndex(name=key, description="", value=val) else: - self.__pydantic_extra__[key] = VectorData( - name=key, description="", value=val - ) + model[key] = VectorData(name=key, description="", value=val) except ValidationError as e: raise ValidationError( f"field {key} cannot be cast to VectorData from {val}" ) from e - return self + return model @model_validator(mode="after") def resolve_targets(self) -> "DynamicTableMixin": @@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel): # find an index idx = None for field_name in self.model_fields_set: + if field_name in self.NON_COLUMN_FIELDS or field_name == key: + continue # implicit name-based index field = getattr(self, field_name) if isinstance(field, VectorIndex) and ( @@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel): """ try: return handler(val) - except ValidationError: + except ValidationError as e: annotation = cls.model_fields[info.field_name].annotation if type(annotation).__name__ == "_UnionGenericAlias": annotation = annotation.__args__[0] - return handler( - annotation( - val, - name=info.field_name, - description=cls.model_fields[info.field_name].description, + try: + # should pass if we're supposed to be a VectorData column + # don't want to override intention here by insisting that it is + # *actually* a VectorData column in case an NDArray has been specified for now + return handler( + annotation( + val, + name=info.field_name, + description=cls.model_fields[info.field_name].description, + ) ) - ) + except Exception: + raise e class AlignedDynamicTableMixin(DynamicTableMixin): diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_6_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_6_0/hdmf_common_table.py index 63d007d..07b20e3 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_6_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_6_0/hdmf_common_table.py @@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel): """ model_config = ConfigDict(extra="allow") - __pydantic_extra__: Dict[str, Union[list, "NDArray", "VectorDataMixin"]] + __pydantic_extra__: Dict[str, Union["VectorDataMixin", "VectorIndexMixin", "NDArray", list]] NON_COLUMN_FIELDS: ClassVar[tuple[str]] = ( "name", "colnames", @@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel): model["colnames"] = colnames return model - @model_validator(mode="after") - def cast_extra_columns(self) -> "DynamicTableMixin": + @model_validator(mode="before") + @classmethod + def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict: """ If extra columns are passed as just lists or arrays, cast to VectorData before we resolve targets for VectorData and VectorIndex pairs. @@ -455,22 +456,20 @@ class DynamicTableMixin(BaseModel): See :meth:`.cast_specified_columns` for handling columns in the class specification """ # if columns are not in the specification, cast to a generic VectorData - for key, val in self.__pydantic_extra__.items(): + for key, val in model.items(): + if key in cls.model_fields: + continue if not isinstance(val, (VectorData, VectorIndex)): try: if key.endswith("_index"): - self.__pydantic_extra__[key] = VectorIndex( - name=key, description="", value=val - ) + model[key] = VectorIndex(name=key, description="", value=val) else: - self.__pydantic_extra__[key] = VectorData( - name=key, description="", value=val - ) + model[key] = VectorData(name=key, description="", value=val) except ValidationError as e: raise ValidationError( f"field {key} cannot be cast to VectorData from {val}" ) from e - return self + return model @model_validator(mode="after") def resolve_targets(self) -> "DynamicTableMixin": @@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel): # find an index idx = None for field_name in self.model_fields_set: + if field_name in self.NON_COLUMN_FIELDS or field_name == key: + continue # implicit name-based index field = getattr(self, field_name) if isinstance(field, VectorIndex) and ( @@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel): """ try: return handler(val) - except ValidationError: + except ValidationError as e: annotation = cls.model_fields[info.field_name].annotation if type(annotation).__name__ == "_UnionGenericAlias": annotation = annotation.__args__[0] - return handler( - annotation( - val, - name=info.field_name, - description=cls.model_fields[info.field_name].description, + try: + # should pass if we're supposed to be a VectorData column + # don't want to override intention here by insisting that it is + # *actually* a VectorData column in case an NDArray has been specified for now + return handler( + annotation( + val, + name=info.field_name, + description=cls.model_fields[info.field_name].description, + ) ) - ) + except Exception: + raise e class AlignedDynamicTableMixin(DynamicTableMixin): diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_7_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_7_0/hdmf_common_table.py index 4be797e..5e7a82f 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_7_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_7_0/hdmf_common_table.py @@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel): """ model_config = ConfigDict(extra="allow") - __pydantic_extra__: Dict[str, Union[list, "NDArray", "VectorDataMixin"]] + __pydantic_extra__: Dict[str, Union["VectorDataMixin", "VectorIndexMixin", "NDArray", list]] NON_COLUMN_FIELDS: ClassVar[tuple[str]] = ( "name", "colnames", @@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel): model["colnames"] = colnames return model - @model_validator(mode="after") - def cast_extra_columns(self) -> "DynamicTableMixin": + @model_validator(mode="before") + @classmethod + def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict: """ If extra columns are passed as just lists or arrays, cast to VectorData before we resolve targets for VectorData and VectorIndex pairs. @@ -455,22 +456,20 @@ class DynamicTableMixin(BaseModel): See :meth:`.cast_specified_columns` for handling columns in the class specification """ # if columns are not in the specification, cast to a generic VectorData - for key, val in self.__pydantic_extra__.items(): + for key, val in model.items(): + if key in cls.model_fields: + continue if not isinstance(val, (VectorData, VectorIndex)): try: if key.endswith("_index"): - self.__pydantic_extra__[key] = VectorIndex( - name=key, description="", value=val - ) + model[key] = VectorIndex(name=key, description="", value=val) else: - self.__pydantic_extra__[key] = VectorData( - name=key, description="", value=val - ) + model[key] = VectorData(name=key, description="", value=val) except ValidationError as e: raise ValidationError( f"field {key} cannot be cast to VectorData from {val}" ) from e - return self + return model @model_validator(mode="after") def resolve_targets(self) -> "DynamicTableMixin": @@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel): # find an index idx = None for field_name in self.model_fields_set: + if field_name in self.NON_COLUMN_FIELDS or field_name == key: + continue # implicit name-based index field = getattr(self, field_name) if isinstance(field, VectorIndex) and ( @@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel): """ try: return handler(val) - except ValidationError: + except ValidationError as e: annotation = cls.model_fields[info.field_name].annotation if type(annotation).__name__ == "_UnionGenericAlias": annotation = annotation.__args__[0] - return handler( - annotation( - val, - name=info.field_name, - description=cls.model_fields[info.field_name].description, + try: + # should pass if we're supposed to be a VectorData column + # don't want to override intention here by insisting that it is + # *actually* a VectorData column in case an NDArray has been specified for now + return handler( + annotation( + val, + name=info.field_name, + description=cls.model_fields[info.field_name].description, + ) ) - ) + except Exception: + raise e class AlignedDynamicTableMixin(DynamicTableMixin): diff --git a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_8_0/hdmf_common_table.py b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_8_0/hdmf_common_table.py index c1b0a8d..7a6660a 100644 --- a/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_8_0/hdmf_common_table.py +++ b/nwb_linkml/src/nwb_linkml/models/pydantic/hdmf_common/v1_8_0/hdmf_common_table.py @@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel): """ model_config = ConfigDict(extra="allow") - __pydantic_extra__: Dict[str, Union[list, "NDArray", "VectorDataMixin"]] + __pydantic_extra__: Dict[str, Union["VectorDataMixin", "VectorIndexMixin", "NDArray", list]] NON_COLUMN_FIELDS: ClassVar[tuple[str]] = ( "name", "colnames", @@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel): model["colnames"] = colnames return model - @model_validator(mode="after") - def cast_extra_columns(self) -> "DynamicTableMixin": + @model_validator(mode="before") + @classmethod + def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict: """ If extra columns are passed as just lists or arrays, cast to VectorData before we resolve targets for VectorData and VectorIndex pairs. @@ -455,22 +456,20 @@ class DynamicTableMixin(BaseModel): See :meth:`.cast_specified_columns` for handling columns in the class specification """ # if columns are not in the specification, cast to a generic VectorData - for key, val in self.__pydantic_extra__.items(): + for key, val in model.items(): + if key in cls.model_fields: + continue if not isinstance(val, (VectorData, VectorIndex)): try: if key.endswith("_index"): - self.__pydantic_extra__[key] = VectorIndex( - name=key, description="", value=val - ) + model[key] = VectorIndex(name=key, description="", value=val) else: - self.__pydantic_extra__[key] = VectorData( - name=key, description="", value=val - ) + model[key] = VectorData(name=key, description="", value=val) except ValidationError as e: raise ValidationError( f"field {key} cannot be cast to VectorData from {val}" ) from e - return self + return model @model_validator(mode="after") def resolve_targets(self) -> "DynamicTableMixin": @@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel): # find an index idx = None for field_name in self.model_fields_set: + if field_name in self.NON_COLUMN_FIELDS or field_name == key: + continue # implicit name-based index field = getattr(self, field_name) if isinstance(field, VectorIndex) and ( @@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel): """ try: return handler(val) - except ValidationError: + except ValidationError as e: annotation = cls.model_fields[info.field_name].annotation if type(annotation).__name__ == "_UnionGenericAlias": annotation = annotation.__args__[0] - return handler( - annotation( - val, - name=info.field_name, - description=cls.model_fields[info.field_name].description, + try: + # should pass if we're supposed to be a VectorData column + # don't want to override intention here by insisting that it is + # *actually* a VectorData column in case an NDArray has been specified for now + return handler( + annotation( + val, + name=info.field_name, + description=cls.model_fields[info.field_name].description, + ) ) - ) + except Exception: + raise e class AlignedDynamicTableMixin(DynamicTableMixin):