Skip to content

Commit 1e944a9

Browse files
matt-bernsteinrobot-ci-heartex
authored andcommitted
chore: FIT-1717: Feature Request: Label Studio SDK - Migrate away from deprecated Pydantic v1 models
GitOrigin-RevId: abb2d0d2be9b8daace6f0c562d7250c207175ebc
1 parent d8d22b6 commit 1e944a9

5 files changed

Lines changed: 47 additions & 23 deletions

File tree

poetry.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/label_studio_sdk/_legacy/client.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44
import json
55
import logging
66
import os
7+
from typing import Optional
78

89
import requests
9-
10-
from typing import Optional
11-
from pydantic import BaseModel, constr, root_validator
10+
from pydantic import BaseModel, constr, model_validator
1211
from requests.adapters import HTTPAdapter
1312

1413
logger = logging.getLogger(__name__)
@@ -24,7 +23,7 @@ class ClientCredentials(BaseModel):
2423
password: Optional[str] = None
2524
api_key: Optional[constr()] = None
2625

27-
@root_validator(pre=True, allow_reuse=True)
26+
@model_validator(mode="before")
2827
def either_key_or_email_password(cls, values):
2928
assert (
3029
"email" in values or "api_key" in values

src/label_studio_sdk/label_interface/control_tags.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
"""
22
"""
33

4-
import xml.etree.ElementTree
54
import json
6-
from typing import Type, Dict, Optional, List, Tuple, Any, Union
7-
from pydantic import BaseModel, confloat, Field, validator
5+
import xml.etree.ElementTree
6+
from typing import Any, Dict, List, Optional, Tuple, Type, Union
87

98
from .base import LabelStudioTag, get_tag_class
10-
from .region import Region
119
from .object_tags import ObjectTag
12-
10+
from .region import Region
11+
from pydantic import BaseModel, Field, confloat, field_validator
1312

1413
_NOT_CONTROL_TAGS = {
1514
"Filter",
@@ -731,7 +730,8 @@ class BrushValue(BaseModel):
731730
format: str = "rle"
732731
rle: List[int]
733732

734-
@validator('rle')
733+
@field_validator("rle")
734+
@classmethod
735735
def validate_rle(cls, rle_data):
736736
if not validate_rle(rle_data):
737737
raise ValueError('Invalid RLE format')
@@ -1400,12 +1400,12 @@ class RelationsTag(ControlTag):
14001400
tag: str = "Relations"
14011401
def validate_value(self, **kwargs) -> bool:
14021402
""" """
1403-
raise NotImplemented("""Should not be called directly, instead
1403+
raise NotImplementedError("""Should not be called directly, instead
14041404
use validate_relation() method found in LabelInterface class""")
14051405

14061406
def label(self, *args, **kwargs):
14071407
""" """
1408-
raise NotImplemented("""
1408+
raise NotImplementedError("""
14091409
Relations work on regions instead of Object tags
14101410
use Regions add_relation() method""")
14111411

@@ -1605,7 +1605,6 @@ def _parse_delimited_list(self, outputs_str: str) -> list:
16051605
Returns:
16061606
list: List of parsed output field names/definitions.
16071607
"""
1608-
import re
16091608
# Split on common delimiters: comma, semicolon, pipe, or whitespace
16101609
# But preserve content inside parentheses for type aliases
16111610
parts = []

src/label_studio_sdk/label_interface/objects.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from typing import Type, Dict, Optional, List, Tuple, Any, Union
2-
from pydantic import BaseModel, Field, confloat, field_serializer
1+
from typing import Any, Dict, List, Optional, Union
32

43
from .region import Region
4+
from pydantic import BaseModel, ConfigDict, Field, field_serializer
55

66

77
def serialize_regions(result):
@@ -24,9 +24,7 @@ class PredictionValue(BaseModel):
2424
score: Optional[float] = 0.00
2525
result: Optional[List[Union[Dict[str, Any], Region]]]
2626

27-
class Config:
28-
populate_by_name = True
29-
protected_namespaces = ()
27+
model_config = ConfigDict(populate_by_name=True, protected_namespaces=())
3028

3129
@field_serializer('result')
3230
def serialize_result(self, result):
@@ -44,8 +42,7 @@ class AnnotationValue(BaseModel):
4442

4543
result: Optional[List[Union[Dict[str, Any], Region]]]
4644

47-
class Config:
48-
populate_by_name = True
45+
model_config = ConfigDict(populate_by_name=True)
4946

5047
@field_serializer('result')
5148
def serialize_result(self, result):
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import importlib
2+
import warnings
3+
4+
5+
def _collect_module_deprecation_warning_messages(module_name: str) -> list[str]:
6+
with warnings.catch_warnings(record=True) as caught:
7+
warnings.simplefilter("always", DeprecationWarning)
8+
module = importlib.import_module(module_name)
9+
importlib.reload(module)
10+
return [str(warning.message) for warning in caught]
11+
12+
13+
def test_legacy_client_import_has_no_v1_root_validator_deprecation_warning():
14+
warning_messages = _collect_module_deprecation_warning_messages("label_studio_sdk._legacy.client")
15+
16+
assert all("V1 style `@root_validator` validators are deprecated" not in message for message in warning_messages)
17+
assert all("`allow_reuse` is deprecated" not in message for message in warning_messages)
18+
19+
20+
def test_control_tags_import_has_no_v1_validator_deprecation_warning():
21+
warning_messages = _collect_module_deprecation_warning_messages("label_studio_sdk.label_interface.control_tags")
22+
23+
assert all("V1 style `@validator` validators are deprecated" not in message for message in warning_messages)
24+
25+
26+
def test_objects_import_has_no_class_config_deprecation_warning():
27+
warning_messages = _collect_module_deprecation_warning_messages("label_studio_sdk.label_interface.objects")
28+
29+
assert all("Support for class-based `config` is deprecated" not in message for message in warning_messages)

0 commit comments

Comments
 (0)