Skip to content

Commit b0d270f

Browse files
committed
[PTDT-4605] Add ability to specify relationship constraints
1 parent 777bfc0 commit b0d270f

File tree

1 file changed

+21
-2
lines changed

1 file changed

+21
-2
lines changed

libs/labelbox/src/labelbox/schema/ontology.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import json
55
from dataclasses import dataclass, field
66
from enum import Enum
7-
from typing import Any, Dict, List, Optional, Union
7+
from typing import Any, Dict, List, Optional, Union, Tuple
88

99
from lbox.exceptions import InconsistentOntologyException
1010

@@ -70,6 +70,15 @@ class Tool:
7070
instructions = "Classification Example")
7171
tool.add_classification(classification)
7272
73+
relationship_tool = Tool(
74+
tool = Tool.Type.RELATIONSHIP,
75+
name = "Relationship Tool Example",
76+
constraints = [
77+
("source_tool_feature_schema_id_1", "target_tool_feature_schema_id_1"),
78+
("source_tool_feature_schema_id_2", "target_tool_feature_schema_id_2")
79+
]
80+
)
81+
7382
Attributes:
7483
tool: (Tool.Type)
7584
name: (str)
@@ -79,6 +88,7 @@ class Tool:
7988
schema_id: (str)
8089
feature_schema_id: (str)
8190
attributes: (list)
91+
constraints: (list of [str, str]) (only available for RELATIONSHIP tool type)
8292
"""
8393

8494
class Type(Enum):
@@ -102,21 +112,28 @@ class Type(Enum):
102112
schema_id: Optional[str] = None
103113
feature_schema_id: Optional[str] = None
104114
attributes: Optional[FeatureSchemaAttributes] = None
115+
constraints: Optional[Tuple[str, str]] = None
105116

106117
def __post_init__(self):
118+
if self.constraints is not None and self.tool != Tool.Type.RELATIONSHIP:
119+
warnings.warn(
120+
"The constraints attribute is only available for Relationship tool. The provided constraints will be ignored."
121+
)
122+
self.constraints = None
107123
if self.attributes is not None:
108124
warnings.warn(
109125
"The attributes for Tools are in beta. The attribute name and signature may change in the future."
110126
)
111127

112128
@classmethod
113129
def from_dict(cls, dictionary: Dict[str, Any]) -> Dict[str, Any]:
130+
tool = Tool.Type(dictionary["tool"])
114131
return cls(
115132
name=dictionary["name"],
116133
schema_id=dictionary.get("schemaNodeId", None),
117134
feature_schema_id=dictionary.get("featureSchemaId", None),
118135
required=dictionary.get("required", False),
119-
tool=Tool.Type(dictionary["tool"]),
136+
tool=tool,
120137
classifications=[
121138
Classification.from_dict(c)
122139
for c in dictionary["classifications"]
@@ -128,6 +145,7 @@ def from_dict(cls, dictionary: Dict[str, Any]) -> Dict[str, Any]:
128145
]
129146
if dictionary.get("attributes")
130147
else None,
148+
constraints=dictionary.get("constraints", None) if tool == Tool.Type.RELATIONSHIP else None,
131149
)
132150

133151
def asdict(self) -> Dict[str, Any]:
@@ -144,6 +162,7 @@ def asdict(self) -> Dict[str, Any]:
144162
"attributes": [a.asdict() for a in self.attributes]
145163
if self.attributes is not None
146164
else None,
165+
"constraints": self.constraints if self.constraints is not None else None,
147166
}
148167

149168
def add_classification(self, classification: Classification) -> None:

0 commit comments

Comments
 (0)