|
8 | 8 | import mimetypes |
9 | 9 | import os |
10 | 10 | import time |
| 11 | +import urllib.parse |
11 | 12 |
|
12 | 13 | from google.api_core import retry |
13 | 14 | import requests |
@@ -55,7 +56,8 @@ def __init__(self, |
55 | 56 | api_key=None, |
56 | 57 | endpoint='https://api.labelbox.com/graphql', |
57 | 58 | enable_experimental=False, |
58 | | - app_url="https://app.labelbox.com"): |
| 59 | + app_url="https://app.labelbox.com", |
| 60 | + rest_endpoint="https://api.labelbox.com/api/v1"): |
59 | 61 | """ Creates and initializes a Labelbox Client. |
60 | 62 |
|
61 | 63 | Logging is defaulted to level WARNING. To receive more verbose |
@@ -88,6 +90,7 @@ def __init__(self, |
88 | 90 | logger.info("Initializing Labelbox client at '%s'", endpoint) |
89 | 91 | self.app_url = app_url |
90 | 92 | self.endpoint = endpoint |
| 93 | + self.rest_endpoint = rest_endpoint |
91 | 94 | self.headers = { |
92 | 95 | 'Accept': 'application/json', |
93 | 96 | 'Content-Type': 'application/json', |
@@ -899,6 +902,129 @@ def create_ontology_from_feature_schemas(self, |
899 | 902 | normalized = {'tools': tools, 'classifications': classifications} |
900 | 903 | return self.create_ontology(name, normalized, media_type) |
901 | 904 |
|
| 905 | + def delete_unused_feature_schema(self, feature_schema_id: str): |
| 906 | + """ |
| 907 | + Deletes a feature schema if it is not used by any ontologies or annotations |
| 908 | + Args: |
| 909 | + feature_schema_id (str): The id of the feature schema to delete |
| 910 | + Example: |
| 911 | + >>> client.delete_unused_feature_schema("cleabc1my012ioqvu5anyaabc") |
| 912 | + """ |
| 913 | + |
| 914 | + endpoint = self.rest_endpoint + "/feature-schemas/" + urllib.parse.quote(feature_schema_id) |
| 915 | + response = requests.delete( |
| 916 | + endpoint, |
| 917 | + headers=self.headers, |
| 918 | + ) |
| 919 | + |
| 920 | + if response.status_code != requests.codes.no_content: |
| 921 | + raise labelbox.exceptions.LabelboxError( |
| 922 | + "Failed to delete the feature schema, message: " + |
| 923 | + str(response.json()['message'])) |
| 924 | + |
| 925 | + def delete_unused_ontology(self, ontology_id: str): |
| 926 | + """ |
| 927 | + Deletes an ontology if it is not used by any annotations |
| 928 | + Args: |
| 929 | + ontology_id (str): The id of the ontology to delete |
| 930 | + Example: |
| 931 | + >>> client.delete_unused_ontology("cleabc1my012ioqvu5anyaabc") |
| 932 | + """ |
| 933 | + |
| 934 | + endpoint = self.rest_endpoint + "/ontologies/" + urllib.parse.quote(ontology_id) |
| 935 | + response = requests.delete( |
| 936 | + endpoint, |
| 937 | + headers=self.headers, |
| 938 | + ) |
| 939 | + |
| 940 | + if response.status_code != requests.codes.no_content: |
| 941 | + raise labelbox.exceptions.LabelboxError( |
| 942 | + "Failed to delete the ontology, message: " + |
| 943 | + str(response.json()['message'])) |
| 944 | + |
| 945 | + def update_feature_schema_title(self, feature_schema_id: str, title: str): |
| 946 | + """ |
| 947 | + Updates a title of a feature schema |
| 948 | + Args: |
| 949 | + feature_schema_id (str): The id of the feature schema to update |
| 950 | + title (str): The new title of the feature schema |
| 951 | + Returns: |
| 952 | + The updated feature schema |
| 953 | + Example: |
| 954 | + >>> client.update_feature_schema_title("cleabc1my012ioqvu5anyaabc", "New Title") |
| 955 | + """ |
| 956 | + |
| 957 | + endpoint = self.rest_endpoint + "/feature-schemas/" + urllib.parse.quote(feature_schema_id) + '/definition' |
| 958 | + response = requests.patch( |
| 959 | + endpoint, |
| 960 | + headers=self.headers, |
| 961 | + json={"title": title}, |
| 962 | + ) |
| 963 | + |
| 964 | + if response.status_code == requests.codes.ok: |
| 965 | + return self.get_feature_schema(feature_schema_id) |
| 966 | + else: |
| 967 | + raise labelbox.exceptions.LabelboxError( |
| 968 | + "Failed to update the feature schema, message: " + |
| 969 | + str(response.json()['message'])) |
| 970 | + |
| 971 | + def upsert_feature_schema(self, normalized: Dict): |
| 972 | + """ |
| 973 | + Upserts a feature schema |
| 974 | + Args: |
| 975 | + normalized: The feature schema to upsert |
| 976 | + Returns: |
| 977 | + The upserted feature schema |
| 978 | + Example: |
| 979 | + Insert a new feature schema |
| 980 | + >>> tool = Tool(name="tool", tool=Tool.Type.BOUNDING_BOX, color="#FF0000") |
| 981 | + >>> client.upsert_feature_schema(tool.asdict()) |
| 982 | + Update an existing feature schema |
| 983 | + >>> tool = Tool(feature_schema_id="cleabc1my012ioqvu5anyaabc", name="tool", tool=Tool.Type.BOUNDING_BOX, color="#FF0000") |
| 984 | + >>> client.upsert_feature_schema(tool.asdict()) |
| 985 | + """ |
| 986 | + |
| 987 | + feature_schema_id = normalized.get( |
| 988 | + "featureSchemaId") or "new_feature_schema_id" |
| 989 | + endpoint = self.rest_endpoint + "/feature-schemas/" + urllib.parse.quote( |
| 990 | + feature_schema_id) |
| 991 | + response = requests.put( |
| 992 | + endpoint, |
| 993 | + headers=self.headers, |
| 994 | + json={"normalized": json.dumps(normalized)}, |
| 995 | + ) |
| 996 | + |
| 997 | + if response.status_code == requests.codes.ok: |
| 998 | + return self.get_feature_schema(response.json()['schemaId']) |
| 999 | + else: |
| 1000 | + raise labelbox.exceptions.LabelboxError( |
| 1001 | + "Failed to upsert the feature schema, message: " + |
| 1002 | + str(response.json()['message'])) |
| 1003 | + |
| 1004 | + def insert_feature_schema_into_ontology(self, feature_schema_id: str, ontology_id: str, position: int): |
| 1005 | + """ |
| 1006 | + Inserts a feature schema into an ontology. If the feature schema is already in the ontology, |
| 1007 | + it will be moved to the new position. |
| 1008 | + Args: |
| 1009 | + feature_schema_id (str): The feature schema id to upsert |
| 1010 | + ontology_id (str): The id of the ontology to insert the feature schema into |
| 1011 | + position (int): The position number of the feature schema in the ontology |
| 1012 | + Example: |
| 1013 | + >>> client.insert_feature_schema_into_ontology("cleabc1my012ioqvu5anyaabc", "clefdvwl7abcgefgu3lyvcde", 2) |
| 1014 | + """ |
| 1015 | + |
| 1016 | + endpoint = self.rest_endpoint + '/ontologies/' + urllib.parse.quote( |
| 1017 | + ontology_id) + "/feature-schemas/" + urllib.parse.quote(feature_schema_id) |
| 1018 | + response = requests.post( |
| 1019 | + endpoint, |
| 1020 | + headers=self.headers, |
| 1021 | + json={"position": position}, |
| 1022 | + ) |
| 1023 | + if response.status_code != requests.codes.created: |
| 1024 | + raise labelbox.exceptions.LabelboxError( |
| 1025 | + "Failed to insert the feature schema into the ontology, message: " + |
| 1026 | + str(response.json()['message'])) |
| 1027 | + |
902 | 1028 | def create_ontology(self, name, normalized, media_type=None) -> Ontology: |
903 | 1029 | """ |
904 | 1030 | Creates an ontology from normalized data |
|
0 commit comments