diff --git a/libs/labelbox/src/labelbox/data/annotation_types/types.py b/libs/labelbox/src/labelbox/data/annotation_types/types.py index 9bb86a4b9..adcadf306 100644 --- a/libs/labelbox/src/labelbox/data/annotation_types/types.py +++ b/libs/labelbox/src/labelbox/data/annotation_types/types.py @@ -5,7 +5,8 @@ from packaging import version import numpy as np -from pydantic import StringConstraints, Field +from pydantic import StringConstraints, Field, ConfigDict +from pydantic_core import core_schema DType = TypeVar("DType") DShape = TypeVar("DShape") @@ -13,11 +14,13 @@ class _TypedArray(np.ndarray, Generic[DType, DShape]): @classmethod - def __get_validators__(cls): - yield cls.validate + def __get_pydantic_core_schema__( + cls, _source_type: type, _model: type + ) -> core_schema.CoreSchema: + return core_schema.no_info_plain_validator_function(cls.validate) @classmethod - def validate(cls, val, field: Field): + def validate(cls, val): if not isinstance(val, np.ndarray): raise TypeError(f"Expected numpy array. Found {type(val)}") return val diff --git a/libs/labelbox/src/labelbox/schema/data_row_metadata.py b/libs/labelbox/src/labelbox/schema/data_row_metadata.py index d6c50b975..4f11170fd 100644 --- a/libs/labelbox/src/labelbox/schema/data_row_metadata.py +++ b/libs/labelbox/src/labelbox/schema/data_row_metadata.py @@ -27,6 +27,7 @@ conlist, ConfigDict, model_serializer, + BeforeValidator, ) from labelbox.schema.ontology import SchemaId @@ -36,6 +37,12 @@ format_iso_from_string, ) +Name = Annotated[ + str, + BeforeValidator(lambda x: str.strip(str(x))), + Field(min_length=1, max_length=100), +] + class DataRowMetadataKind(Enum): number = "CustomMetadataNumber" @@ -49,7 +56,7 @@ class DataRowMetadataKind(Enum): # Metadata schema class DataRowMetadataSchema(BaseModel): uid: SchemaId - name: str = Field(strip_whitespace=True, min_length=1, max_length=100) + name: Name reserved: bool kind: DataRowMetadataKind options: Optional[List["DataRowMetadataSchema"]] = None diff --git a/libs/labelbox/src/labelbox/schema/labeling_service_dashboard.py b/libs/labelbox/src/labelbox/schema/labeling_service_dashboard.py index e2c6fa26b..2f91af7af 100644 --- a/libs/labelbox/src/labelbox/schema/labeling_service_dashboard.py +++ b/libs/labelbox/src/labelbox/schema/labeling_service_dashboard.py @@ -3,7 +3,7 @@ from typing import Any, Dict, List, Optional, Union from lbox.exceptions import ResourceNotFoundError -from pydantic import BaseModel, Field, model_validator +from pydantic import BaseModel, Field, model_validator, model_serializer from labelbox.pagination import PaginatedCollection from labelbox.schema.labeling_service_status import LabelingServiceStatus @@ -50,7 +50,7 @@ class LabelingServiceDashboard(_CamelCaseMixin): Represent labeling service data for a project NOTE on tasks vs data rows. A task is a unit of work that is assigned to a user. A data row is a unit of data that needs to be labeled. - In the current implementation a task reprsents a single data row. However tasks only exists when a labeler start labeling a data row. + In the current implementation a task represents a single data row. However tasks only exists when a labeler start labeling a data row. So if a data row is not labeled, it will not have a task associated with it. Therefore the number of tasks can be less than the number of data rows. Attributes: @@ -221,8 +221,9 @@ def convert_boost_data(cls, data): return data - def dict(self, *args, **kwargs): - row = super().dict(*args, **kwargs) + @model_serializer() + def ser_model(self): + row = self row.pop("client") row["service_type"] = self.service_type return row diff --git a/libs/labelbox/src/labelbox/schema/search_filters.py b/libs/labelbox/src/labelbox/schema/search_filters.py index 13b158678..e61e29ad8 100644 --- a/libs/labelbox/src/labelbox/schema/search_filters.py +++ b/libs/labelbox/src/labelbox/schema/search_filters.py @@ -5,7 +5,7 @@ from typing_extensions import Annotated -from pydantic import BaseModel, Field, field_validator +from pydantic import BaseModel, Field, field_validator, ConfigDict from labelbox.schema.labeling_service_status import LabelingServiceStatus from labelbox.utils import format_iso_datetime @@ -15,8 +15,7 @@ class BaseSearchFilter(BaseModel): Shared code for all search filters """ - class Config: - use_enum_values = True + model_config = ConfigDict(use_enum_values=True) class OperationTypeEnum(Enum): diff --git a/libs/labelbox/tests/integration/test_data_rows.py b/libs/labelbox/tests/integration/test_data_rows.py index 78a1efb3a..7d777a28a 100644 --- a/libs/labelbox/tests/integration/test_data_rows.py +++ b/libs/labelbox/tests/integration/test_data_rows.py @@ -1,7 +1,7 @@ import json import os import uuid -from datetime import datetime +from datetime import datetime, timezone from tempfile import NamedTemporaryFile from unittest.mock import patch @@ -95,7 +95,7 @@ def tile_content(): def make_metadata_fields(): msg = "A message" - time = datetime.utcnow() + time = datetime.now(timezone.utc) fields = [ DataRowMetadataField(schema_id=SPLIT_SCHEMA_ID, value=TEST_SPLIT_ID), @@ -107,7 +107,7 @@ def make_metadata_fields(): def make_metadata_fields_dict(): msg = "A message" - time = datetime.utcnow() + time = datetime.now(timezone.utc) fields = [ {"schema_id": SPLIT_SCHEMA_ID, "value": TEST_SPLIT_ID},