regenerate models

This commit is contained in:
sneakers-the-rat 2024-08-13 23:39:11 -07:00
parent 43ff3503dc
commit d61d1ecf22
Signed by untrusted user who does not match committer: jonny
GPG key ID: 6DCB96EF1E4D232D
12 changed files with 300 additions and 216 deletions

View file

@ -245,7 +245,7 @@ class DynamicTableMixin(BaseModel):
""" """
model_config = ConfigDict(extra="allow") 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]] = ( NON_COLUMN_FIELDS: ClassVar[tuple[str]] = (
"name", "name",
"colnames", "colnames",
@ -445,8 +445,9 @@ class DynamicTableMixin(BaseModel):
model["colnames"] = colnames model["colnames"] = colnames
return model return model
@model_validator(mode="after") @model_validator(mode="before")
def cast_extra_columns(self) -> "DynamicTableMixin": @classmethod
def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict:
""" """
If extra columns are passed as just lists or arrays, cast to VectorData If extra columns are passed as just lists or arrays, cast to VectorData
before we resolve targets for VectorData and VectorIndex pairs. 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 See :meth:`.cast_specified_columns` for handling columns in the class specification
""" """
# if columns are not in the specification, cast to a generic VectorData # 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)): if not isinstance(val, (VectorData, VectorIndex)):
try: try:
if key.endswith("_index"): if key.endswith("_index"):
self.__pydantic_extra__[key] = VectorIndex( model[key] = VectorIndex(name=key, description="", value=val)
name=key, description="", value=val
)
else: else:
self.__pydantic_extra__[key] = VectorData( model[key] = VectorData(name=key, description="", value=val)
name=key, description="", value=val
)
except ValidationError as e: except ValidationError as e:
raise ValidationError( raise ValidationError(
f"field {key} cannot be cast to VectorData from {val}" f"field {key} cannot be cast to VectorData from {val}"
) from e ) from e
return self return model
@model_validator(mode="after") @model_validator(mode="after")
def resolve_targets(self) -> "DynamicTableMixin": def resolve_targets(self) -> "DynamicTableMixin":
@ -481,6 +480,8 @@ class DynamicTableMixin(BaseModel):
# find an index # find an index
idx = None idx = None
for field_name in self.model_fields_set: 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 # implicit name-based index
field = getattr(self, field_name) field = getattr(self, field_name)
if isinstance(field, VectorIndex) and ( if isinstance(field, VectorIndex) and (
@ -519,17 +520,23 @@ class DynamicTableMixin(BaseModel):
""" """
try: try:
return handler(val) return handler(val)
except ValidationError: except ValidationError as e:
annotation = cls.model_fields[info.field_name].annotation annotation = cls.model_fields[info.field_name].annotation
if type(annotation).__name__ == "_UnionGenericAlias": if type(annotation).__name__ == "_UnionGenericAlias":
annotation = annotation.__args__[0] annotation = annotation.__args__[0]
return handler( try:
annotation( # should pass if we're supposed to be a VectorData column
val, # don't want to override intention here by insisting that it is
name=info.field_name, # *actually* a VectorData column in case an NDArray has been specified for now
description=cls.model_fields[info.field_name].description, return handler(
annotation(
val,
name=info.field_name,
description=cls.model_fields[info.field_name].description,
)
) )
) except Exception:
raise e
class AlignedDynamicTableMixin(DynamicTableMixin): class AlignedDynamicTableMixin(DynamicTableMixin):

View file

@ -245,7 +245,7 @@ class DynamicTableMixin(BaseModel):
""" """
model_config = ConfigDict(extra="allow") 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]] = ( NON_COLUMN_FIELDS: ClassVar[tuple[str]] = (
"name", "name",
"colnames", "colnames",
@ -445,8 +445,9 @@ class DynamicTableMixin(BaseModel):
model["colnames"] = colnames model["colnames"] = colnames
return model return model
@model_validator(mode="after") @model_validator(mode="before")
def cast_extra_columns(self) -> "DynamicTableMixin": @classmethod
def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict:
""" """
If extra columns are passed as just lists or arrays, cast to VectorData If extra columns are passed as just lists or arrays, cast to VectorData
before we resolve targets for VectorData and VectorIndex pairs. 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 See :meth:`.cast_specified_columns` for handling columns in the class specification
""" """
# if columns are not in the specification, cast to a generic VectorData # 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)): if not isinstance(val, (VectorData, VectorIndex)):
try: try:
if key.endswith("_index"): if key.endswith("_index"):
self.__pydantic_extra__[key] = VectorIndex( model[key] = VectorIndex(name=key, description="", value=val)
name=key, description="", value=val
)
else: else:
self.__pydantic_extra__[key] = VectorData( model[key] = VectorData(name=key, description="", value=val)
name=key, description="", value=val
)
except ValidationError as e: except ValidationError as e:
raise ValidationError( raise ValidationError(
f"field {key} cannot be cast to VectorData from {val}" f"field {key} cannot be cast to VectorData from {val}"
) from e ) from e
return self return model
@model_validator(mode="after") @model_validator(mode="after")
def resolve_targets(self) -> "DynamicTableMixin": def resolve_targets(self) -> "DynamicTableMixin":
@ -481,6 +480,8 @@ class DynamicTableMixin(BaseModel):
# find an index # find an index
idx = None idx = None
for field_name in self.model_fields_set: 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 # implicit name-based index
field = getattr(self, field_name) field = getattr(self, field_name)
if isinstance(field, VectorIndex) and ( if isinstance(field, VectorIndex) and (
@ -519,17 +520,23 @@ class DynamicTableMixin(BaseModel):
""" """
try: try:
return handler(val) return handler(val)
except ValidationError: except ValidationError as e:
annotation = cls.model_fields[info.field_name].annotation annotation = cls.model_fields[info.field_name].annotation
if type(annotation).__name__ == "_UnionGenericAlias": if type(annotation).__name__ == "_UnionGenericAlias":
annotation = annotation.__args__[0] annotation = annotation.__args__[0]
return handler( try:
annotation( # should pass if we're supposed to be a VectorData column
val, # don't want to override intention here by insisting that it is
name=info.field_name, # *actually* a VectorData column in case an NDArray has been specified for now
description=cls.model_fields[info.field_name].description, return handler(
annotation(
val,
name=info.field_name,
description=cls.model_fields[info.field_name].description,
)
) )
) except Exception:
raise e
class AlignedDynamicTableMixin(DynamicTableMixin): class AlignedDynamicTableMixin(DynamicTableMixin):

View file

@ -245,7 +245,7 @@ class DynamicTableMixin(BaseModel):
""" """
model_config = ConfigDict(extra="allow") 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]] = ( NON_COLUMN_FIELDS: ClassVar[tuple[str]] = (
"name", "name",
"colnames", "colnames",
@ -445,8 +445,9 @@ class DynamicTableMixin(BaseModel):
model["colnames"] = colnames model["colnames"] = colnames
return model return model
@model_validator(mode="after") @model_validator(mode="before")
def cast_extra_columns(self) -> "DynamicTableMixin": @classmethod
def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict:
""" """
If extra columns are passed as just lists or arrays, cast to VectorData If extra columns are passed as just lists or arrays, cast to VectorData
before we resolve targets for VectorData and VectorIndex pairs. 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 See :meth:`.cast_specified_columns` for handling columns in the class specification
""" """
# if columns are not in the specification, cast to a generic VectorData # 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)): if not isinstance(val, (VectorData, VectorIndex)):
try: try:
if key.endswith("_index"): if key.endswith("_index"):
self.__pydantic_extra__[key] = VectorIndex( model[key] = VectorIndex(name=key, description="", value=val)
name=key, description="", value=val
)
else: else:
self.__pydantic_extra__[key] = VectorData( model[key] = VectorData(name=key, description="", value=val)
name=key, description="", value=val
)
except ValidationError as e: except ValidationError as e:
raise ValidationError( raise ValidationError(
f"field {key} cannot be cast to VectorData from {val}" f"field {key} cannot be cast to VectorData from {val}"
) from e ) from e
return self return model
@model_validator(mode="after") @model_validator(mode="after")
def resolve_targets(self) -> "DynamicTableMixin": def resolve_targets(self) -> "DynamicTableMixin":
@ -481,6 +480,8 @@ class DynamicTableMixin(BaseModel):
# find an index # find an index
idx = None idx = None
for field_name in self.model_fields_set: 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 # implicit name-based index
field = getattr(self, field_name) field = getattr(self, field_name)
if isinstance(field, VectorIndex) and ( if isinstance(field, VectorIndex) and (
@ -519,17 +520,23 @@ class DynamicTableMixin(BaseModel):
""" """
try: try:
return handler(val) return handler(val)
except ValidationError: except ValidationError as e:
annotation = cls.model_fields[info.field_name].annotation annotation = cls.model_fields[info.field_name].annotation
if type(annotation).__name__ == "_UnionGenericAlias": if type(annotation).__name__ == "_UnionGenericAlias":
annotation = annotation.__args__[0] annotation = annotation.__args__[0]
return handler( try:
annotation( # should pass if we're supposed to be a VectorData column
val, # don't want to override intention here by insisting that it is
name=info.field_name, # *actually* a VectorData column in case an NDArray has been specified for now
description=cls.model_fields[info.field_name].description, return handler(
annotation(
val,
name=info.field_name,
description=cls.model_fields[info.field_name].description,
)
) )
) except Exception:
raise e
class AlignedDynamicTableMixin(DynamicTableMixin): class AlignedDynamicTableMixin(DynamicTableMixin):

View file

@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel):
""" """
model_config = ConfigDict(extra="allow") 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]] = ( NON_COLUMN_FIELDS: ClassVar[tuple[str]] = (
"name", "name",
"colnames", "colnames",
@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel):
model["colnames"] = colnames model["colnames"] = colnames
return model return model
@model_validator(mode="after") @model_validator(mode="before")
def cast_extra_columns(self) -> "DynamicTableMixin": @classmethod
def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict:
""" """
If extra columns are passed as just lists or arrays, cast to VectorData If extra columns are passed as just lists or arrays, cast to VectorData
before we resolve targets for VectorData and VectorIndex pairs. 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 See :meth:`.cast_specified_columns` for handling columns in the class specification
""" """
# if columns are not in the specification, cast to a generic VectorData # 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)): if not isinstance(val, (VectorData, VectorIndex)):
try: try:
if key.endswith("_index"): if key.endswith("_index"):
self.__pydantic_extra__[key] = VectorIndex( model[key] = VectorIndex(name=key, description="", value=val)
name=key, description="", value=val
)
else: else:
self.__pydantic_extra__[key] = VectorData( model[key] = VectorData(name=key, description="", value=val)
name=key, description="", value=val
)
except ValidationError as e: except ValidationError as e:
raise ValidationError( raise ValidationError(
f"field {key} cannot be cast to VectorData from {val}" f"field {key} cannot be cast to VectorData from {val}"
) from e ) from e
return self return model
@model_validator(mode="after") @model_validator(mode="after")
def resolve_targets(self) -> "DynamicTableMixin": def resolve_targets(self) -> "DynamicTableMixin":
@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel):
# find an index # find an index
idx = None idx = None
for field_name in self.model_fields_set: 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 # implicit name-based index
field = getattr(self, field_name) field = getattr(self, field_name)
if isinstance(field, VectorIndex) and ( if isinstance(field, VectorIndex) and (
@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel):
""" """
try: try:
return handler(val) return handler(val)
except ValidationError: except ValidationError as e:
annotation = cls.model_fields[info.field_name].annotation annotation = cls.model_fields[info.field_name].annotation
if type(annotation).__name__ == "_UnionGenericAlias": if type(annotation).__name__ == "_UnionGenericAlias":
annotation = annotation.__args__[0] annotation = annotation.__args__[0]
return handler( try:
annotation( # should pass if we're supposed to be a VectorData column
val, # don't want to override intention here by insisting that it is
name=info.field_name, # *actually* a VectorData column in case an NDArray has been specified for now
description=cls.model_fields[info.field_name].description, return handler(
annotation(
val,
name=info.field_name,
description=cls.model_fields[info.field_name].description,
)
) )
) except Exception:
raise e
class AlignedDynamicTableMixin(DynamicTableMixin): class AlignedDynamicTableMixin(DynamicTableMixin):

View file

@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel):
""" """
model_config = ConfigDict(extra="allow") 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]] = ( NON_COLUMN_FIELDS: ClassVar[tuple[str]] = (
"name", "name",
"colnames", "colnames",
@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel):
model["colnames"] = colnames model["colnames"] = colnames
return model return model
@model_validator(mode="after") @model_validator(mode="before")
def cast_extra_columns(self) -> "DynamicTableMixin": @classmethod
def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict:
""" """
If extra columns are passed as just lists or arrays, cast to VectorData If extra columns are passed as just lists or arrays, cast to VectorData
before we resolve targets for VectorData and VectorIndex pairs. 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 See :meth:`.cast_specified_columns` for handling columns in the class specification
""" """
# if columns are not in the specification, cast to a generic VectorData # 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)): if not isinstance(val, (VectorData, VectorIndex)):
try: try:
if key.endswith("_index"): if key.endswith("_index"):
self.__pydantic_extra__[key] = VectorIndex( model[key] = VectorIndex(name=key, description="", value=val)
name=key, description="", value=val
)
else: else:
self.__pydantic_extra__[key] = VectorData( model[key] = VectorData(name=key, description="", value=val)
name=key, description="", value=val
)
except ValidationError as e: except ValidationError as e:
raise ValidationError( raise ValidationError(
f"field {key} cannot be cast to VectorData from {val}" f"field {key} cannot be cast to VectorData from {val}"
) from e ) from e
return self return model
@model_validator(mode="after") @model_validator(mode="after")
def resolve_targets(self) -> "DynamicTableMixin": def resolve_targets(self) -> "DynamicTableMixin":
@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel):
# find an index # find an index
idx = None idx = None
for field_name in self.model_fields_set: 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 # implicit name-based index
field = getattr(self, field_name) field = getattr(self, field_name)
if isinstance(field, VectorIndex) and ( if isinstance(field, VectorIndex) and (
@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel):
""" """
try: try:
return handler(val) return handler(val)
except ValidationError: except ValidationError as e:
annotation = cls.model_fields[info.field_name].annotation annotation = cls.model_fields[info.field_name].annotation
if type(annotation).__name__ == "_UnionGenericAlias": if type(annotation).__name__ == "_UnionGenericAlias":
annotation = annotation.__args__[0] annotation = annotation.__args__[0]
return handler( try:
annotation( # should pass if we're supposed to be a VectorData column
val, # don't want to override intention here by insisting that it is
name=info.field_name, # *actually* a VectorData column in case an NDArray has been specified for now
description=cls.model_fields[info.field_name].description, return handler(
annotation(
val,
name=info.field_name,
description=cls.model_fields[info.field_name].description,
)
) )
) except Exception:
raise e
class AlignedDynamicTableMixin(DynamicTableMixin): class AlignedDynamicTableMixin(DynamicTableMixin):

View file

@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel):
""" """
model_config = ConfigDict(extra="allow") 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]] = ( NON_COLUMN_FIELDS: ClassVar[tuple[str]] = (
"name", "name",
"colnames", "colnames",
@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel):
model["colnames"] = colnames model["colnames"] = colnames
return model return model
@model_validator(mode="after") @model_validator(mode="before")
def cast_extra_columns(self) -> "DynamicTableMixin": @classmethod
def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict:
""" """
If extra columns are passed as just lists or arrays, cast to VectorData If extra columns are passed as just lists or arrays, cast to VectorData
before we resolve targets for VectorData and VectorIndex pairs. 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 See :meth:`.cast_specified_columns` for handling columns in the class specification
""" """
# if columns are not in the specification, cast to a generic VectorData # 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)): if not isinstance(val, (VectorData, VectorIndex)):
try: try:
if key.endswith("_index"): if key.endswith("_index"):
self.__pydantic_extra__[key] = VectorIndex( model[key] = VectorIndex(name=key, description="", value=val)
name=key, description="", value=val
)
else: else:
self.__pydantic_extra__[key] = VectorData( model[key] = VectorData(name=key, description="", value=val)
name=key, description="", value=val
)
except ValidationError as e: except ValidationError as e:
raise ValidationError( raise ValidationError(
f"field {key} cannot be cast to VectorData from {val}" f"field {key} cannot be cast to VectorData from {val}"
) from e ) from e
return self return model
@model_validator(mode="after") @model_validator(mode="after")
def resolve_targets(self) -> "DynamicTableMixin": def resolve_targets(self) -> "DynamicTableMixin":
@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel):
# find an index # find an index
idx = None idx = None
for field_name in self.model_fields_set: 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 # implicit name-based index
field = getattr(self, field_name) field = getattr(self, field_name)
if isinstance(field, VectorIndex) and ( if isinstance(field, VectorIndex) and (
@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel):
""" """
try: try:
return handler(val) return handler(val)
except ValidationError: except ValidationError as e:
annotation = cls.model_fields[info.field_name].annotation annotation = cls.model_fields[info.field_name].annotation
if type(annotation).__name__ == "_UnionGenericAlias": if type(annotation).__name__ == "_UnionGenericAlias":
annotation = annotation.__args__[0] annotation = annotation.__args__[0]
return handler( try:
annotation( # should pass if we're supposed to be a VectorData column
val, # don't want to override intention here by insisting that it is
name=info.field_name, # *actually* a VectorData column in case an NDArray has been specified for now
description=cls.model_fields[info.field_name].description, return handler(
annotation(
val,
name=info.field_name,
description=cls.model_fields[info.field_name].description,
)
) )
) except Exception:
raise e
class AlignedDynamicTableMixin(DynamicTableMixin): class AlignedDynamicTableMixin(DynamicTableMixin):

View file

@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel):
""" """
model_config = ConfigDict(extra="allow") 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]] = ( NON_COLUMN_FIELDS: ClassVar[tuple[str]] = (
"name", "name",
"colnames", "colnames",
@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel):
model["colnames"] = colnames model["colnames"] = colnames
return model return model
@model_validator(mode="after") @model_validator(mode="before")
def cast_extra_columns(self) -> "DynamicTableMixin": @classmethod
def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict:
""" """
If extra columns are passed as just lists or arrays, cast to VectorData If extra columns are passed as just lists or arrays, cast to VectorData
before we resolve targets for VectorData and VectorIndex pairs. 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 See :meth:`.cast_specified_columns` for handling columns in the class specification
""" """
# if columns are not in the specification, cast to a generic VectorData # 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)): if not isinstance(val, (VectorData, VectorIndex)):
try: try:
if key.endswith("_index"): if key.endswith("_index"):
self.__pydantic_extra__[key] = VectorIndex( model[key] = VectorIndex(name=key, description="", value=val)
name=key, description="", value=val
)
else: else:
self.__pydantic_extra__[key] = VectorData( model[key] = VectorData(name=key, description="", value=val)
name=key, description="", value=val
)
except ValidationError as e: except ValidationError as e:
raise ValidationError( raise ValidationError(
f"field {key} cannot be cast to VectorData from {val}" f"field {key} cannot be cast to VectorData from {val}"
) from e ) from e
return self return model
@model_validator(mode="after") @model_validator(mode="after")
def resolve_targets(self) -> "DynamicTableMixin": def resolve_targets(self) -> "DynamicTableMixin":
@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel):
# find an index # find an index
idx = None idx = None
for field_name in self.model_fields_set: 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 # implicit name-based index
field = getattr(self, field_name) field = getattr(self, field_name)
if isinstance(field, VectorIndex) and ( if isinstance(field, VectorIndex) and (
@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel):
""" """
try: try:
return handler(val) return handler(val)
except ValidationError: except ValidationError as e:
annotation = cls.model_fields[info.field_name].annotation annotation = cls.model_fields[info.field_name].annotation
if type(annotation).__name__ == "_UnionGenericAlias": if type(annotation).__name__ == "_UnionGenericAlias":
annotation = annotation.__args__[0] annotation = annotation.__args__[0]
return handler( try:
annotation( # should pass if we're supposed to be a VectorData column
val, # don't want to override intention here by insisting that it is
name=info.field_name, # *actually* a VectorData column in case an NDArray has been specified for now
description=cls.model_fields[info.field_name].description, return handler(
annotation(
val,
name=info.field_name,
description=cls.model_fields[info.field_name].description,
)
) )
) except Exception:
raise e
class AlignedDynamicTableMixin(DynamicTableMixin): class AlignedDynamicTableMixin(DynamicTableMixin):

View file

@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel):
""" """
model_config = ConfigDict(extra="allow") 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]] = ( NON_COLUMN_FIELDS: ClassVar[tuple[str]] = (
"name", "name",
"colnames", "colnames",
@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel):
model["colnames"] = colnames model["colnames"] = colnames
return model return model
@model_validator(mode="after") @model_validator(mode="before")
def cast_extra_columns(self) -> "DynamicTableMixin": @classmethod
def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict:
""" """
If extra columns are passed as just lists or arrays, cast to VectorData If extra columns are passed as just lists or arrays, cast to VectorData
before we resolve targets for VectorData and VectorIndex pairs. 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 See :meth:`.cast_specified_columns` for handling columns in the class specification
""" """
# if columns are not in the specification, cast to a generic VectorData # 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)): if not isinstance(val, (VectorData, VectorIndex)):
try: try:
if key.endswith("_index"): if key.endswith("_index"):
self.__pydantic_extra__[key] = VectorIndex( model[key] = VectorIndex(name=key, description="", value=val)
name=key, description="", value=val
)
else: else:
self.__pydantic_extra__[key] = VectorData( model[key] = VectorData(name=key, description="", value=val)
name=key, description="", value=val
)
except ValidationError as e: except ValidationError as e:
raise ValidationError( raise ValidationError(
f"field {key} cannot be cast to VectorData from {val}" f"field {key} cannot be cast to VectorData from {val}"
) from e ) from e
return self return model
@model_validator(mode="after") @model_validator(mode="after")
def resolve_targets(self) -> "DynamicTableMixin": def resolve_targets(self) -> "DynamicTableMixin":
@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel):
# find an index # find an index
idx = None idx = None
for field_name in self.model_fields_set: 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 # implicit name-based index
field = getattr(self, field_name) field = getattr(self, field_name)
if isinstance(field, VectorIndex) and ( if isinstance(field, VectorIndex) and (
@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel):
""" """
try: try:
return handler(val) return handler(val)
except ValidationError: except ValidationError as e:
annotation = cls.model_fields[info.field_name].annotation annotation = cls.model_fields[info.field_name].annotation
if type(annotation).__name__ == "_UnionGenericAlias": if type(annotation).__name__ == "_UnionGenericAlias":
annotation = annotation.__args__[0] annotation = annotation.__args__[0]
return handler( try:
annotation( # should pass if we're supposed to be a VectorData column
val, # don't want to override intention here by insisting that it is
name=info.field_name, # *actually* a VectorData column in case an NDArray has been specified for now
description=cls.model_fields[info.field_name].description, return handler(
annotation(
val,
name=info.field_name,
description=cls.model_fields[info.field_name].description,
)
) )
) except Exception:
raise e
class AlignedDynamicTableMixin(DynamicTableMixin): class AlignedDynamicTableMixin(DynamicTableMixin):

View file

@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel):
""" """
model_config = ConfigDict(extra="allow") 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]] = ( NON_COLUMN_FIELDS: ClassVar[tuple[str]] = (
"name", "name",
"colnames", "colnames",
@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel):
model["colnames"] = colnames model["colnames"] = colnames
return model return model
@model_validator(mode="after") @model_validator(mode="before")
def cast_extra_columns(self) -> "DynamicTableMixin": @classmethod
def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict:
""" """
If extra columns are passed as just lists or arrays, cast to VectorData If extra columns are passed as just lists or arrays, cast to VectorData
before we resolve targets for VectorData and VectorIndex pairs. 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 See :meth:`.cast_specified_columns` for handling columns in the class specification
""" """
# if columns are not in the specification, cast to a generic VectorData # 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)): if not isinstance(val, (VectorData, VectorIndex)):
try: try:
if key.endswith("_index"): if key.endswith("_index"):
self.__pydantic_extra__[key] = VectorIndex( model[key] = VectorIndex(name=key, description="", value=val)
name=key, description="", value=val
)
else: else:
self.__pydantic_extra__[key] = VectorData( model[key] = VectorData(name=key, description="", value=val)
name=key, description="", value=val
)
except ValidationError as e: except ValidationError as e:
raise ValidationError( raise ValidationError(
f"field {key} cannot be cast to VectorData from {val}" f"field {key} cannot be cast to VectorData from {val}"
) from e ) from e
return self return model
@model_validator(mode="after") @model_validator(mode="after")
def resolve_targets(self) -> "DynamicTableMixin": def resolve_targets(self) -> "DynamicTableMixin":
@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel):
# find an index # find an index
idx = None idx = None
for field_name in self.model_fields_set: 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 # implicit name-based index
field = getattr(self, field_name) field = getattr(self, field_name)
if isinstance(field, VectorIndex) and ( if isinstance(field, VectorIndex) and (
@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel):
""" """
try: try:
return handler(val) return handler(val)
except ValidationError: except ValidationError as e:
annotation = cls.model_fields[info.field_name].annotation annotation = cls.model_fields[info.field_name].annotation
if type(annotation).__name__ == "_UnionGenericAlias": if type(annotation).__name__ == "_UnionGenericAlias":
annotation = annotation.__args__[0] annotation = annotation.__args__[0]
return handler( try:
annotation( # should pass if we're supposed to be a VectorData column
val, # don't want to override intention here by insisting that it is
name=info.field_name, # *actually* a VectorData column in case an NDArray has been specified for now
description=cls.model_fields[info.field_name].description, return handler(
annotation(
val,
name=info.field_name,
description=cls.model_fields[info.field_name].description,
)
) )
) except Exception:
raise e
class AlignedDynamicTableMixin(DynamicTableMixin): class AlignedDynamicTableMixin(DynamicTableMixin):

View file

@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel):
""" """
model_config = ConfigDict(extra="allow") 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]] = ( NON_COLUMN_FIELDS: ClassVar[tuple[str]] = (
"name", "name",
"colnames", "colnames",
@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel):
model["colnames"] = colnames model["colnames"] = colnames
return model return model
@model_validator(mode="after") @model_validator(mode="before")
def cast_extra_columns(self) -> "DynamicTableMixin": @classmethod
def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict:
""" """
If extra columns are passed as just lists or arrays, cast to VectorData If extra columns are passed as just lists or arrays, cast to VectorData
before we resolve targets for VectorData and VectorIndex pairs. 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 See :meth:`.cast_specified_columns` for handling columns in the class specification
""" """
# if columns are not in the specification, cast to a generic VectorData # 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)): if not isinstance(val, (VectorData, VectorIndex)):
try: try:
if key.endswith("_index"): if key.endswith("_index"):
self.__pydantic_extra__[key] = VectorIndex( model[key] = VectorIndex(name=key, description="", value=val)
name=key, description="", value=val
)
else: else:
self.__pydantic_extra__[key] = VectorData( model[key] = VectorData(name=key, description="", value=val)
name=key, description="", value=val
)
except ValidationError as e: except ValidationError as e:
raise ValidationError( raise ValidationError(
f"field {key} cannot be cast to VectorData from {val}" f"field {key} cannot be cast to VectorData from {val}"
) from e ) from e
return self return model
@model_validator(mode="after") @model_validator(mode="after")
def resolve_targets(self) -> "DynamicTableMixin": def resolve_targets(self) -> "DynamicTableMixin":
@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel):
# find an index # find an index
idx = None idx = None
for field_name in self.model_fields_set: 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 # implicit name-based index
field = getattr(self, field_name) field = getattr(self, field_name)
if isinstance(field, VectorIndex) and ( if isinstance(field, VectorIndex) and (
@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel):
""" """
try: try:
return handler(val) return handler(val)
except ValidationError: except ValidationError as e:
annotation = cls.model_fields[info.field_name].annotation annotation = cls.model_fields[info.field_name].annotation
if type(annotation).__name__ == "_UnionGenericAlias": if type(annotation).__name__ == "_UnionGenericAlias":
annotation = annotation.__args__[0] annotation = annotation.__args__[0]
return handler( try:
annotation( # should pass if we're supposed to be a VectorData column
val, # don't want to override intention here by insisting that it is
name=info.field_name, # *actually* a VectorData column in case an NDArray has been specified for now
description=cls.model_fields[info.field_name].description, return handler(
annotation(
val,
name=info.field_name,
description=cls.model_fields[info.field_name].description,
)
) )
) except Exception:
raise e
class AlignedDynamicTableMixin(DynamicTableMixin): class AlignedDynamicTableMixin(DynamicTableMixin):

View file

@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel):
""" """
model_config = ConfigDict(extra="allow") 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]] = ( NON_COLUMN_FIELDS: ClassVar[tuple[str]] = (
"name", "name",
"colnames", "colnames",
@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel):
model["colnames"] = colnames model["colnames"] = colnames
return model return model
@model_validator(mode="after") @model_validator(mode="before")
def cast_extra_columns(self) -> "DynamicTableMixin": @classmethod
def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict:
""" """
If extra columns are passed as just lists or arrays, cast to VectorData If extra columns are passed as just lists or arrays, cast to VectorData
before we resolve targets for VectorData and VectorIndex pairs. 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 See :meth:`.cast_specified_columns` for handling columns in the class specification
""" """
# if columns are not in the specification, cast to a generic VectorData # 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)): if not isinstance(val, (VectorData, VectorIndex)):
try: try:
if key.endswith("_index"): if key.endswith("_index"):
self.__pydantic_extra__[key] = VectorIndex( model[key] = VectorIndex(name=key, description="", value=val)
name=key, description="", value=val
)
else: else:
self.__pydantic_extra__[key] = VectorData( model[key] = VectorData(name=key, description="", value=val)
name=key, description="", value=val
)
except ValidationError as e: except ValidationError as e:
raise ValidationError( raise ValidationError(
f"field {key} cannot be cast to VectorData from {val}" f"field {key} cannot be cast to VectorData from {val}"
) from e ) from e
return self return model
@model_validator(mode="after") @model_validator(mode="after")
def resolve_targets(self) -> "DynamicTableMixin": def resolve_targets(self) -> "DynamicTableMixin":
@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel):
# find an index # find an index
idx = None idx = None
for field_name in self.model_fields_set: 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 # implicit name-based index
field = getattr(self, field_name) field = getattr(self, field_name)
if isinstance(field, VectorIndex) and ( if isinstance(field, VectorIndex) and (
@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel):
""" """
try: try:
return handler(val) return handler(val)
except ValidationError: except ValidationError as e:
annotation = cls.model_fields[info.field_name].annotation annotation = cls.model_fields[info.field_name].annotation
if type(annotation).__name__ == "_UnionGenericAlias": if type(annotation).__name__ == "_UnionGenericAlias":
annotation = annotation.__args__[0] annotation = annotation.__args__[0]
return handler( try:
annotation( # should pass if we're supposed to be a VectorData column
val, # don't want to override intention here by insisting that it is
name=info.field_name, # *actually* a VectorData column in case an NDArray has been specified for now
description=cls.model_fields[info.field_name].description, return handler(
annotation(
val,
name=info.field_name,
description=cls.model_fields[info.field_name].description,
)
) )
) except Exception:
raise e
class AlignedDynamicTableMixin(DynamicTableMixin): class AlignedDynamicTableMixin(DynamicTableMixin):

View file

@ -246,7 +246,7 @@ class DynamicTableMixin(BaseModel):
""" """
model_config = ConfigDict(extra="allow") 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]] = ( NON_COLUMN_FIELDS: ClassVar[tuple[str]] = (
"name", "name",
"colnames", "colnames",
@ -446,8 +446,9 @@ class DynamicTableMixin(BaseModel):
model["colnames"] = colnames model["colnames"] = colnames
return model return model
@model_validator(mode="after") @model_validator(mode="before")
def cast_extra_columns(self) -> "DynamicTableMixin": @classmethod
def cast_extra_columns(cls, model: Dict[str, Any]) -> Dict:
""" """
If extra columns are passed as just lists or arrays, cast to VectorData If extra columns are passed as just lists or arrays, cast to VectorData
before we resolve targets for VectorData and VectorIndex pairs. 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 See :meth:`.cast_specified_columns` for handling columns in the class specification
""" """
# if columns are not in the specification, cast to a generic VectorData # 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)): if not isinstance(val, (VectorData, VectorIndex)):
try: try:
if key.endswith("_index"): if key.endswith("_index"):
self.__pydantic_extra__[key] = VectorIndex( model[key] = VectorIndex(name=key, description="", value=val)
name=key, description="", value=val
)
else: else:
self.__pydantic_extra__[key] = VectorData( model[key] = VectorData(name=key, description="", value=val)
name=key, description="", value=val
)
except ValidationError as e: except ValidationError as e:
raise ValidationError( raise ValidationError(
f"field {key} cannot be cast to VectorData from {val}" f"field {key} cannot be cast to VectorData from {val}"
) from e ) from e
return self return model
@model_validator(mode="after") @model_validator(mode="after")
def resolve_targets(self) -> "DynamicTableMixin": def resolve_targets(self) -> "DynamicTableMixin":
@ -482,6 +481,8 @@ class DynamicTableMixin(BaseModel):
# find an index # find an index
idx = None idx = None
for field_name in self.model_fields_set: 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 # implicit name-based index
field = getattr(self, field_name) field = getattr(self, field_name)
if isinstance(field, VectorIndex) and ( if isinstance(field, VectorIndex) and (
@ -520,17 +521,23 @@ class DynamicTableMixin(BaseModel):
""" """
try: try:
return handler(val) return handler(val)
except ValidationError: except ValidationError as e:
annotation = cls.model_fields[info.field_name].annotation annotation = cls.model_fields[info.field_name].annotation
if type(annotation).__name__ == "_UnionGenericAlias": if type(annotation).__name__ == "_UnionGenericAlias":
annotation = annotation.__args__[0] annotation = annotation.__args__[0]
return handler( try:
annotation( # should pass if we're supposed to be a VectorData column
val, # don't want to override intention here by insisting that it is
name=info.field_name, # *actually* a VectorData column in case an NDArray has been specified for now
description=cls.model_fields[info.field_name].description, return handler(
annotation(
val,
name=info.field_name,
description=cls.model_fields[info.field_name].description,
)
) )
) except Exception:
raise e
class AlignedDynamicTableMixin(DynamicTableMixin): class AlignedDynamicTableMixin(DynamicTableMixin):