diff --git a/labelbox/schema/data_row_metadata.py b/labelbox/schema/data_row_metadata.py index 47242e10b..666e88a16 100644 --- a/labelbox/schema/data_row_metadata.py +++ b/labelbox/schema/data_row_metadata.py @@ -158,7 +158,7 @@ def _lookup_in_index_by_name(reserved_index, custom_index, name): elif name in custom_index: return custom_index[name] else: - raise KeyError(f"There is no metadata with name {name}") + raise KeyError(f"There is no metadata with name '{name}'") def get_by_name( self, name: str @@ -528,8 +528,8 @@ def _batch_upsert( data_row_id=m.data_row_id, fields=list( chain.from_iterable( - self._parse_upsert(m) for m in m.fields))).dict( - by_alias=True)) + self._parse_upsert(f, m.data_row_id) + for f in m.fields))).dict(by_alias=True)) res = _batch_operations(_batch_upsert, items, self._batch_size) return res @@ -689,8 +689,12 @@ def _upsert_schema( def _load_option_by_name(self, metadatum: DataRowMetadataField): is_value_a_valid_schema_id = metadatum.value in self.fields_by_id if not is_value_a_valid_schema_id: - metadatum.value = self.get_by_name( - metadatum.name)[metadatum.value].uid + metadatum_by_name = self.get_by_name(metadatum.name) + if metadatum.value not in metadatum_by_name: + raise KeyError( + f"There is no enum option by name '{metadatum.value}' for enum name '{metadatum.name}'" + ) + metadatum.value = metadatum_by_name[metadatum.value].uid def _load_schema_id_by_name(self, metadatum: DataRowMetadataField): """ @@ -706,7 +710,9 @@ def _load_schema_id_by_name(self, metadatum: DataRowMetadataField): self._load_option_by_name(metadatum) def _parse_upsert( - self, metadatum: DataRowMetadataField + self, + metadatum: DataRowMetadataField, + data_row_id: Optional[str] = None ) -> List[_UpsertDataRowMetadataInput]: """Format for metadata upserts to GQL""" @@ -720,21 +726,27 @@ def _parse_upsert( f"Schema Id `{metadatum.schema_id}` not found in ontology") schema = self.fields_by_id[metadatum.schema_id] - - if schema.kind == DataRowMetadataKind.datetime: - parsed = _validate_parse_datetime(metadatum) - elif schema.kind == DataRowMetadataKind.string: - parsed = _validate_parse_text(metadatum) - elif schema.kind == DataRowMetadataKind.number: - parsed = _validate_parse_number(metadatum) - elif schema.kind == DataRowMetadataKind.embedding: - parsed = _validate_parse_embedding(metadatum) - elif schema.kind == DataRowMetadataKind.enum: - parsed = _validate_enum_parse(schema, metadatum) - elif schema.kind == DataRowMetadataKind.option: - raise ValueError("An Option id should not be set as the Schema id") - else: - raise ValueError(f"Unknown type: {schema}") + try: + if schema.kind == DataRowMetadataKind.datetime: + parsed = _validate_parse_datetime(metadatum) + elif schema.kind == DataRowMetadataKind.string: + parsed = _validate_parse_text(metadatum) + elif schema.kind == DataRowMetadataKind.number: + parsed = _validate_parse_number(metadatum) + elif schema.kind == DataRowMetadataKind.embedding: + parsed = _validate_parse_embedding(metadatum) + elif schema.kind == DataRowMetadataKind.enum: + parsed = _validate_enum_parse(schema, metadatum) + elif schema.kind == DataRowMetadataKind.option: + raise ValueError( + "An Option id should not be set as the Schema id") + else: + raise ValueError(f"Unknown type: {schema}") + except ValueError as e: + error_str = f"Could not validate metadata [{metadatum}]" + if data_row_id: + error_str += f", data_row_id='{data_row_id}'" + raise ValueError(f"{error_str}. Reason: {e}") return [_UpsertDataRowMetadataInput(**p) for p in parsed] @@ -824,7 +836,7 @@ def _validate_parse_datetime( field.value = datetime.fromisoformat(field.value) elif not isinstance(field.value, datetime): raise TypeError( - f"value for datetime fields must be either a string or datetime object. Found {type(field.value)}" + f"Value for datetime fields must be either a string or datetime object. Found {type(field.value)}" ) return [{ @@ -842,7 +854,7 @@ def _validate_parse_text( if len(field.value) > String.max_length: raise ValueError( - f"string fields cannot exceed {String.max_length} characters.") + f"String fields cannot exceed {String.max_length} characters.") return [field.dict(by_alias=True)]