Skip to content

Commit 5af2944

Browse files
authored
Merge pull request #958 from Labelbox/PTDT-1106
[PTDT-1106] Implemented delete_feature_schema_from_ontology client method
2 parents 24cf09a + 6f5dc14 commit 5af2944

File tree

3 files changed

+84
-2
lines changed

3 files changed

+84
-2
lines changed

labelbox/client.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
_LABELBOX_API_KEY = "LABELBOX_API_KEY"
4545

4646

47+
class DeleteFeatureFromOntologyResult:
48+
archived: bool
49+
deleted: bool
50+
51+
4752
class Client:
4853
""" A Labelbox client.
4954
@@ -931,7 +936,6 @@ def delete_unused_ontology(self, ontology_id: str) -> None:
931936
Example:
932937
>>> client.delete_unused_ontology("cleabc1my012ioqvu5anyaabc")
933938
"""
934-
935939
endpoint = self.rest_endpoint + "/ontologies/" + urllib.parse.quote(
936940
ontology_id)
937941
response = requests.delete(
@@ -1597,3 +1601,48 @@ def get_model_slice(self, slice_id) -> ModelSlice:
15971601
"""
15981602
res = self.execute(query_str, {"id": slice_id})
15991603
return Entity.ModelSlice(self, res["getSavedQuery"])
1604+
1605+
def delete_feature_schema_from_ontology(
1606+
self, ontology_id: str,
1607+
feature_schema_id: str) -> DeleteFeatureFromOntologyResult:
1608+
"""
1609+
Deletes or archives a feature schema from an ontology.
1610+
If the feature schema is a root level node with associated labels, it will be archived.
1611+
If the feature schema is a nested node in the ontology and does not have associated labels, it will be deleted.
1612+
If the feature schema is a nested node in the ontology and has associated labels, it will not be deleted.
1613+
1614+
Args:
1615+
ontology_id (str): The ID of the ontology.
1616+
feature_schema_id (str): The ID of the feature schema.
1617+
1618+
Returns:
1619+
DeleteFeatureFromOntologyResult: The result of the feature schema removal.
1620+
1621+
Example:
1622+
>>> client.remove_feature_schema_from_ontology(<ontology_id>, <feature_schema_id>)
1623+
"""
1624+
ontology_endpoint = self.rest_endpoint + "/ontologies/" + urllib.parse.quote(
1625+
ontology_id) + "/feature-schemas/" + urllib.parse.quote(
1626+
feature_schema_id)
1627+
response = requests.delete(
1628+
ontology_endpoint,
1629+
headers=self.headers,
1630+
)
1631+
1632+
if response.status_code == requests.codes.ok:
1633+
response_json = response.json()
1634+
if response_json['archived'] == True:
1635+
logger.info(
1636+
'Feature schema was archived from the ontology because it had associated labels.'
1637+
)
1638+
elif response_json['deleted'] == True:
1639+
logger.info(
1640+
'Feature schema was successfully removed from the ontology')
1641+
result = DeleteFeatureFromOntologyResult()
1642+
result.archived = bool(response_json['archived'])
1643+
result.deleted = bool(response_json['deleted'])
1644+
return result
1645+
else:
1646+
raise labelbox.exceptions.LabelboxError(
1647+
"Failed to remove feature schema from ontology, message: " +
1648+
str(response.json()['message']))

tests/integration/conftest.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from labelbox import Client
1313
from labelbox import LabelingFrontend
14-
from labelbox import OntologyBuilder, Tool, Option, Classification
14+
from labelbox import OntologyBuilder, Tool, Option, Classification, MediaType
1515
from labelbox.orm import query
1616
from labelbox.pagination import PaginatedCollection
1717
from labelbox.schema.annotation_import import LabelImport
@@ -525,3 +525,25 @@ def func(project):
525525
time.sleep(2)
526526

527527
return func
528+
529+
530+
@pytest.fixture
531+
def ontology(client):
532+
ontology_builder = OntologyBuilder(
533+
tools=[
534+
Tool(tool=Tool.Type.BBOX, name="Box 1", color="#ff0000"),
535+
Tool(tool=Tool.Type.BBOX, name="Box 2", color="#ff0000")
536+
],
537+
classifications=[
538+
Classification(name="Root Class",
539+
class_type=Classification.Type.RADIO,
540+
options=[
541+
Option(value="1", label="Option 1"),
542+
Option(value="2", label="Option 2")
543+
])
544+
])
545+
ontology = client.create_ontology('Integration Test Ontology',
546+
ontology_builder.asdict(),
547+
MediaType.Image)
548+
yield ontology
549+
client.delete_unused_ontology(ontology.uid)

tests/integration/test_ontology.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@
66
import time
77

88

9+
def test_delete_tool_feature_from_ontology(client, ontology):
10+
feature_schema_to_delete = ontology.normalized['tools'][0]
11+
assert len(ontology.normalized['tools']) == 2
12+
result = client.delete_feature_schema_from_ontology(
13+
ontology.uid, feature_schema_to_delete['featureSchemaId'])
14+
assert result.deleted == True
15+
assert result.archived == False
16+
updatedOntology = client.get_ontology(ontology.uid)
17+
assert len(updatedOntology.normalized['tools']) == 1
18+
19+
920
@pytest.mark.skip(reason="normalized ontology contains Relationship, "
1021
"which is not finalized yet. introduce this back when"
1122
"Relationship feature is complete and we introduce"

0 commit comments

Comments
 (0)