Skip to content

Commit c41a144

Browse files
committed
update to make the ability to separate between label and value and update to test cases
1 parent 47bab9d commit c41a144

File tree

2 files changed

+55
-42
lines changed

2 files changed

+55
-42
lines changed

labelbox/schema/ontology.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,19 @@ class Option:
3434
options: (list)
3535
"""
3636
value: Union[str, int]
37+
label: Optional[Union[str, int]] = None
3738
schema_id: Optional[str] = None
3839
feature_schema_id: Optional[FeatureSchemaId] = None
3940
options: List["Classification"] = field(default_factory=list)
4041

41-
@property
42-
def label(self):
43-
return self.value
42+
def __post_init__(self):
43+
if self.label is None:
44+
self.label = self.value
4445

4546
@classmethod
4647
def from_dict(cls, dictionary: Dict[str, Any]):
4748
return cls(value=dictionary["value"],
49+
label=dictionary["label"],
4850
schema_id=dictionary.get("schemaNodeId", None),
4951
feature_schema_id=dictionary.get("featureSchemaId", None),
5052
options=[
@@ -101,7 +103,6 @@ class Classification:
101103
schema_id: (str)
102104
feature_schema_id: (str)
103105
"""
104-
105106
class Type(Enum):
106107
TEXT = "text"
107108
CHECKLIST = "checklist"
@@ -123,12 +124,13 @@ def name(self):
123124

124125
@classmethod
125126
def from_dict(cls, dictionary: Dict[str, Any]):
126-
return cls(class_type=cls.Type(dictionary["type"]),
127-
instructions=dictionary["instructions"],
128-
required=dictionary.get("required", False),
129-
options=[Option.from_dict(o) for o in dictionary["options"]],
130-
schema_id=dictionary.get("schemaNodeId", None),
131-
feature_schema_id=dictionary.get("featureSchemaId", None))
127+
return cls(
128+
class_type=cls.Type(dictionary["type"]),
129+
instructions=dictionary["instructions"],
130+
required=dictionary.get("required", False),
131+
options=[Option.from_dict(o) for o in dictionary["options"]],
132+
schema_id=dictionary.get("schemaNodeId", None),
133+
feature_schema_id=dictionary.get("featureSchemaId", None))
132134

133135
def asdict(self) -> Dict[str, Any]:
134136
if self.class_type in self._REQUIRES_OPTIONS \
@@ -183,7 +185,6 @@ class Tool:
183185
schema_id: (str)
184186
feature_schema_id: (str)
185187
"""
186-
187188
class Type(Enum):
188189
POLYGON = "polygon"
189190
SEGMENTATION = "superpixel"
@@ -225,8 +226,8 @@ def asdict(self) -> Dict[str, Any]:
225226
}
226227

227228
def add_classification(self, classification: Classification):
228-
if classification.instructions in (
229-
c.instructions for c in self.classifications):
229+
if classification.instructions in (c.instructions
230+
for c in self.classifications):
230231
raise InconsistentOntologyException(
231232
f"Duplicate nested classification '{classification.instructions}' "
232233
f"for tool '{self.name}'")
@@ -347,8 +348,8 @@ def add_tool(self, tool: Tool):
347348
self.tools.append(tool)
348349

349350
def add_classification(self, classification: Classification):
350-
if classification.instructions in (
351-
c.instructions for c in self.classifications):
351+
if classification.instructions in (c.instructions
352+
for c in self.classifications):
352353
raise InconsistentOntologyException(
353354
f"Duplicate classification instructions '{classification.instructions}'. "
354355
)

tests/integration/test_ontology.py

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,39 +22,39 @@
2222
"classifications": []
2323
}, {
2424
"schemaNodeId":
25-
None,
25+
None,
2626
"featureSchemaId":
27-
None,
27+
None,
2828
"required":
29-
False,
29+
False,
3030
"name":
31-
"bbox",
31+
"bbox",
3232
"color":
33-
"#FF0000",
33+
"#FF0000",
3434
"tool":
35-
"rectangle",
35+
"rectangle",
3636
"classifications": [{
3737
"schemaNodeId":
38-
None,
38+
None,
3939
"featureSchemaId":
40-
None,
40+
None,
4141
"required":
42-
True,
42+
True,
4343
"instructions":
44-
"nested classification",
44+
"nested classification",
4545
"name":
46-
"nested classification",
46+
"nested classification",
4747
"type":
48-
"radio",
48+
"radio",
4949
"options": [{
5050
"schemaNodeId":
51-
None,
51+
None,
5252
"featureSchemaId":
53-
None,
53+
None,
5454
"label":
55-
"first",
55+
"first",
5656
"value":
57-
"first",
57+
"first",
5858
"options": [{
5959
"schemaNodeId": None,
6060
"featureSchemaId": None,
@@ -107,28 +107,28 @@
107107
}],
108108
"classifications": [{
109109
"schemaNodeId":
110-
None,
110+
None,
111111
"featureSchemaId":
112-
None,
112+
None,
113113
"required":
114-
True,
114+
True,
115115
"instructions":
116-
"This is a question.",
116+
"This is a question.",
117117
"name":
118-
"This is a question.",
118+
"This is a question.",
119119
"type":
120-
"radio",
120+
"radio",
121121
"options": [{
122122
"schemaNodeId": None,
123123
"featureSchemaId": None,
124124
"label": "yes",
125-
"value": "yes",
125+
"value": "definitely yes",
126126
"options": []
127127
}, {
128128
"schemaNodeId": None,
129129
"featureSchemaId": None,
130130
"label": "no",
131-
"value": "no",
131+
"value": "definitely not",
132132
"options": []
133133
}]
134134
}]
@@ -149,12 +149,22 @@ def test_create_classification(class_type) -> None:
149149

150150
@pytest.mark.parametrize("value, expected_value, typing",
151151
[(3, 3, int), ("string", "string", str)])
152-
def test_create_option(value, expected_value, typing) -> None:
152+
def test_create_option_with_value(value, expected_value, typing) -> None:
153153
o = Option(value=value)
154154
assert (o.value == expected_value)
155155
assert (o.value == o.label)
156156

157157

158+
@pytest.mark.parametrize("value, label, expected_value, typing",
159+
[(3, 2, 3, int),
160+
("string", "another string", "string", str)])
161+
def test_create_option_with_value_and_label(value, label, expected_value,
162+
typing) -> None:
163+
o = Option(value=value, label=label)
164+
assert (o.value == expected_value)
165+
assert o.value != o.label
166+
167+
158168
def test_create_empty_ontology() -> None:
159169
o = OntologyBuilder()
160170
assert (o.tools == [])
@@ -200,7 +210,8 @@ def test_add_ontology_classification() -> None:
200210

201211
def test_tool_add_classification() -> None:
202212
t = Tool(tool=Tool.Type.SEGMENTATION, name="segmentation")
203-
c = Classification(class_type=Classification.Type.TEXT, instructions="text")
213+
c = Classification(class_type=Classification.Type.TEXT,
214+
instructions="text")
204215
t.add_classification(c)
205216
assert t.classifications == [c]
206217

@@ -223,7 +234,8 @@ def test_classification_add_option() -> None:
223234

224235
def test_option_add_option() -> None:
225236
o = Option(value="option")
226-
c = Classification(class_type=Classification.Type.TEXT, instructions="text")
237+
c = Classification(class_type=Classification.Type.TEXT,
238+
instructions="text")
227239
o.add_option(c)
228240
assert o.options == [c]
229241

0 commit comments

Comments
 (0)