Skip to content

Commit 9abd8d0

Browse files
committed
[PTDT-4605] Add ability to specify relationship constraints
1 parent 1784891 commit 9abd8d0

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

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

Lines changed: 25 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

@@ -71,6 +71,15 @@ class Tool:
7171
instructions = "Classification Example")
7272
tool.add_classification(classification)
7373
74+
relationship_tool = Tool(
75+
tool = Tool.Type.RELATIONSHIP,
76+
name = "Relationship Tool Example",
77+
constraints = [
78+
("source_tool_feature_schema_id_1", "target_tool_feature_schema_id_1"),
79+
("source_tool_feature_schema_id_2", "target_tool_feature_schema_id_2")
80+
]
81+
)
82+
7483
Attributes:
7584
tool: (Tool.Type)
7685
name: (str)
@@ -80,6 +89,7 @@ class Tool:
8089
schema_id: (str)
8190
feature_schema_id: (str)
8291
attributes: (list)
92+
constraints: (list of [str, str]) (only available for RELATIONSHIP tool type)
8393
"""
8494

8595
class Type(Enum):
@@ -103,21 +113,28 @@ class Type(Enum):
103113
schema_id: Optional[str] = None
104114
feature_schema_id: Optional[str] = None
105115
attributes: Optional[FeatureSchemaAttributes] = None
116+
constraints: Optional[Tuple[str, str]] = None
106117

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

113129
@classmethod
114130
def from_dict(cls, dictionary: Dict[str, Any]) -> Dict[str, Any]:
131+
tool = Tool.Type(dictionary["tool"])
115132
return cls(
116133
name=dictionary["name"],
117134
schema_id=dictionary.get("schemaNodeId", None),
118135
feature_schema_id=dictionary.get("featureSchemaId", None),
119136
required=dictionary.get("required", False),
120-
tool=Tool.Type(dictionary["tool"]),
137+
tool=tool,
121138
classifications=[
122139
Classification.from_dict(c)
123140
for c in dictionary["classifications"]
@@ -129,6 +146,9 @@ def from_dict(cls, dictionary: Dict[str, Any]) -> Dict[str, Any]:
129146
]
130147
if dictionary.get("attributes")
131148
else None,
149+
constraints=dictionary.get("constraints", None)
150+
if tool == Tool.Type.RELATIONSHIP
151+
else None,
132152
)
133153

134154
def asdict(self) -> Dict[str, Any]:
@@ -145,6 +165,9 @@ def asdict(self) -> Dict[str, Any]:
145165
"attributes": [a.asdict() for a in self.attributes]
146166
if self.attributes is not None
147167
else None,
168+
"constraints": self.constraints
169+
if self.constraints is not None
170+
else None,
148171
}
149172

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

0 commit comments

Comments
 (0)