Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Changelog

# Version 3.40.0 (YYYY-MM-DD)
* Added new client method is_feature_schema_archived
* Added new client method unarchive_feature_schema_node
* Added new client method delete_feature_schema_from_ontology

## Added
* Insert newest changelogs here
Expand Down
49 changes: 44 additions & 5 deletions labelbox/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from labelbox.schema.role import Role
from labelbox.schema.slice import CatalogSlice, ModelSlice
from labelbox.schema.queue_mode import QueueMode
from labelbox.schema.ontology import Ontology, DeleteFeatureFromOntologyResult

from labelbox.schema.media_type import MediaType, get_media_type_validation_error

Expand All @@ -44,11 +45,6 @@
_LABELBOX_API_KEY = "LABELBOX_API_KEY"


class DeleteFeatureFromOntologyResult:
archived: bool
deleted: bool


class Client:
""" A Labelbox client.

Expand Down Expand Up @@ -1578,6 +1574,49 @@ def get_catalog_slice(self, slice_id) -> CatalogSlice:
res = self.execute(query_str, {'id': slice_id})
return Entity.CatalogSlice(self, res['getSavedQuery'])

def is_feature_schema_archived(self, ontology_id: str,
feature_schema_id: str) -> bool:
"""
Returns true if a feature schema is archived in the specified ontology, returns false otherwise.

Args:
feature_schema_id (str): The ID of the feature schema
ontology_id (str): The ID of the ontology
Returns:
bool
"""

ontology_endpoint = self.rest_endpoint + "/ontologies/" + urllib.parse.quote(
ontology_id)
response = requests.get(
ontology_endpoint,
headers=self.headers,
)

if response.status_code == requests.codes.ok:
feature_schema_nodes = response.json()['featureSchemaNodes']
tools = feature_schema_nodes['tools']
classifications = feature_schema_nodes['classifications']
relationships = feature_schema_nodes['relationships']
feature_schema_node_list = tools + classifications + relationships
filtered_feature_schema_nodes = [
feature_schema_node
for feature_schema_node in feature_schema_node_list
if feature_schema_node['featureSchemaId'] == feature_schema_id
]
if filtered_feature_schema_nodes:
return bool(filtered_feature_schema_nodes[0]['archived'])
else:
raise labelbox.exceptions.LabelboxError(
"The specified feature schema was not in the ontology.")

elif response.status_code == 404:
raise labelbox.exceptions.ResourceNotFoundError(
Ontology, ontology_id)
else:
raise labelbox.exceptions.LabelboxError(
"Failed to get the feature schema archived status.")

def get_model_slice(self, slice_id) -> ModelSlice:
"""
Fetches a Model Slice by ID.
Expand Down
10 changes: 10 additions & 0 deletions labelbox/schema/ontology.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,21 @@
from labelbox.exceptions import InconsistentOntologyException
from labelbox.orm.db_object import DbObject
from labelbox.orm.model import Field, Relationship
import json

FeatureSchemaId: Type[str] = constr(min_length=25, max_length=25)
SchemaId: Type[str] = constr(min_length=25, max_length=25)


class DeleteFeatureFromOntologyResult:
archived: bool
deleted: bool

def __str__(self):
return "<%s %s>" % (self.__class__.__name__.split(".")[-1],
json.dumps(self.__dict__))


class FeatureSchema(DbObject):
name = Field.String("name")
color = Field.String("name")
Expand Down
37 changes: 37 additions & 0 deletions tests/integration/test_ontology.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,43 @@
import time


def test_feature_schema_is_not_archived(client, ontology):
feature_schema_to_check = ontology.normalized['tools'][0]
result = client.is_feature_schema_archived(
ontology.uid, feature_schema_to_check['featureSchemaId'])
assert result == False


def test_feature_schema_is_archived(client, configured_project_with_label):
project, _, _, label = configured_project_with_label
ontology = project.ontology()
feature_schema_id = ontology.normalized['tools'][0]['featureSchemaId']
result = client.delete_feature_schema_from_ontology(ontology.uid,
feature_schema_id)
assert result.archived == True and result.deleted == False
assert client.is_feature_schema_archived(ontology.uid,
feature_schema_id) == True


def test_is_feature_schema_archived_for_non_existing_feature_schema(
client, ontology):
with pytest.raises(
Exception,
match="The specified feature schema was not in the ontology"):
client.is_feature_schema_archived(ontology.uid,
'invalid-feature-schema-id')


def test_is_feature_schema_archived_for_non_existing_ontology(client, ontology):
feature_schema_to_unarchive = ontology.normalized['tools'][0]
with pytest.raises(
Exception,
match="Resource 'Ontology' not found for params: 'invalid-ontology'"
):
client.is_feature_schema_archived(
'invalid-ontology', feature_schema_to_unarchive['featureSchemaId'])


def test_delete_tool_feature_from_ontology(client, ontology):
feature_schema_to_delete = ontology.normalized['tools'][0]
assert len(ontology.normalized['tools']) == 2
Expand Down