Skip to content

Commit 30910f4

Browse files
authored
Add search by name for get_catalog_slice() and get_catalog_slices() (#1953)
2 parents 3fe2b9e + 4df79c5 commit 30910f4

File tree

2 files changed

+178
-10
lines changed

2 files changed

+178
-10
lines changed

libs/labelbox/src/labelbox/client.py

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,17 +1809,14 @@ def _format_failed_rows(
18091809
def get_catalog(self) -> Catalog:
18101810
return Catalog(client=self)
18111811

1812-
def get_catalog_slice(self, slice_id) -> CatalogSlice:
1812+
def get_catalog_slices(self) -> List[CatalogSlice]:
18131813
"""
1814-
Fetches a Catalog Slice by ID.
1815-
1816-
Args:
1817-
slice_id (str): The ID of the Slice
1814+
Fetches all slices of the given entity type.
18181815
Returns:
1819-
CatalogSlice
1816+
List[CatalogSlice]: A list of CatalogSlice objects.
18201817
"""
1821-
query_str = """query getSavedQueryPyApi($id: ID!) {
1822-
getSavedQuery(id: $id) {
1818+
query_str = """query GetCatalogSavedQueriesPyApi {
1819+
catalogSavedQueries {
18231820
id
18241821
name
18251822
description
@@ -1828,9 +1825,62 @@ def get_catalog_slice(self, slice_id) -> CatalogSlice:
18281825
updatedAt
18291826
}
18301827
}
1828+
"""
1829+
res = self.execute(query_str)
1830+
return [CatalogSlice(self, sl) for sl in res["catalogSavedQueries"]]
1831+
1832+
def get_catalog_slice(
1833+
self, slice_id: Optional[str] = None, slice_name: Optional[str] = None
1834+
) -> Union[CatalogSlice, List[CatalogSlice]]:
18311835
"""
1832-
res = self.execute(query_str, {"id": slice_id})
1833-
return Entity.CatalogSlice(self, res["getSavedQuery"])
1836+
Fetches a Slice using either the slice ID or the slice name.
1837+
1838+
Args:
1839+
slice_id (Optional[str]): The ID of the Slice.
1840+
slice_name (Optional[str]): The name of the Slice.
1841+
1842+
Returns:
1843+
Union[CatalogSlice, List[CatalogSlice], ModelSlice, List[ModelSlice]]:
1844+
The corresponding Slice object or list of Slice objects.
1845+
1846+
Raises:
1847+
ValueError: If neither or both id and name are provided.
1848+
ResourceNotFoundError: If the slice is not found.
1849+
"""
1850+
if (slice_id is None and slice_name is None) or (
1851+
slice_id is not None and slice_name is not None
1852+
):
1853+
raise ValueError("Provide exactly one of id or name")
1854+
1855+
if slice_id is not None:
1856+
query_str = """query getSavedQueryPyApi($id: ID!) {
1857+
getSavedQuery(id: $id) {
1858+
id
1859+
name
1860+
description
1861+
filter
1862+
createdAt
1863+
updatedAt
1864+
}
1865+
}
1866+
"""
1867+
1868+
res = self.execute(query_str, {"id": slice_id})
1869+
if res is None:
1870+
raise ResourceNotFoundError(CatalogSlice, {"id": slice_id})
1871+
1872+
return CatalogSlice(self, res["getSavedQuery"])
1873+
1874+
else:
1875+
slices = self.get_catalog_slices()
1876+
matches = [s for s in slices if s.name == slice_name]
1877+
1878+
if not matches:
1879+
raise ResourceNotFoundError(CatalogSlice, {"name": slice_name})
1880+
elif len(matches) > 1:
1881+
return matches
1882+
else:
1883+
return matches[0]
18341884

18351885
def is_feature_schema_archived(
18361886
self, ontology_id: str, feature_schema_id: str
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
from typing import Optional
2+
from labelbox import Client, CatalogSlice
3+
4+
5+
def _create_catalog_slice(
6+
client: Client, name: str, description: Optional[str] = None
7+
) -> str:
8+
"""Creates a catalog slice for testing purposes.
9+
10+
Args:
11+
client (Client): Labelbox client instance
12+
name (str): Name of the catalog slice
13+
description (str): Description of the catalog slice
14+
15+
Returns:
16+
str: ID of the created catalog slice
17+
"""
18+
19+
mutation = """mutation CreateCatalogSlicePyApi($name: String!, $description: String, $query: SearchServiceQuery!, $sorting: [SearchServiceSorting!]) {
20+
createCatalogSavedQuery(
21+
args: {name: $name, description: $description, filter: $query, sorting: $sorting}
22+
) {
23+
id
24+
name
25+
description
26+
filter
27+
sorting
28+
catalogCount {
29+
count
30+
}
31+
}
32+
}
33+
"""
34+
35+
params = {
36+
"description": description,
37+
"name": name,
38+
"query": [
39+
{
40+
"type": "media_attribute_asset_type",
41+
"assetType": {"type": "asset_type", "assetTypes": ["image"]},
42+
}
43+
],
44+
"sorting": [
45+
{
46+
"field": {
47+
"field": "dataRowCreatedAt",
48+
"verboseName": "Created At",
49+
},
50+
"direction": "DESC",
51+
"metadataSchemaId": None,
52+
}
53+
],
54+
}
55+
56+
result = client.execute(mutation, params, experimental=True)
57+
58+
return result["createCatalogSavedQuery"].get("id")
59+
60+
61+
def _delete_catalog_slice(client, slice_id: str) -> bool:
62+
mutation = """mutation DeleteCatalogSlicePyApi($id: ID!) {
63+
deleteSavedQuery(args: { id: $id }) {
64+
success
65+
}
66+
}
67+
"""
68+
69+
params = {"id": slice_id}
70+
71+
operation_done = True
72+
try:
73+
client.execute(mutation, params, experimental=True)
74+
except Exception as ex:
75+
operation_done = False
76+
77+
return operation_done
78+
79+
80+
def test_get_slice(client):
81+
# Pre-cleaning
82+
slices = (
83+
s
84+
for s in client.get_catalog_slices()
85+
if s.name in ["Test Slice 1", "Test Slice 2"]
86+
)
87+
for slice in slices:
88+
_delete_catalog_slice(client, slice.id)
89+
90+
# Create slices
91+
slice_id_1 = _create_catalog_slice(
92+
client, "Test Slice 1", "Slice created for SDK test."
93+
)
94+
slice_id_2 = _create_catalog_slice(
95+
client, "Test Slice 2", "Slice created for SDK test."
96+
)
97+
# Create slice 2b - with the same name as slice 2
98+
slice_id_2b = _create_catalog_slice(
99+
client, "Test Slice 2", "Slice created for SDK test."
100+
)
101+
102+
# Assert get slice 1 by ID
103+
slice_1 = client.get_catalog_slice(slice_id_1)
104+
assert isinstance(slice_1, CatalogSlice)
105+
106+
slice_1 = client.get_catalog_slice(slice_name="Test Slice 1")
107+
assert isinstance(slice_1, CatalogSlice)
108+
109+
slices_2 = client.get_catalog_slice(slice_name="Test Slice 2")
110+
assert len(slices_2) == 2
111+
assert isinstance(slices_2, list) and all(
112+
[isinstance(item, CatalogSlice) for item in slices_2]
113+
)
114+
115+
# Cleaning - Delete slices
116+
_delete_catalog_slice(client, slice_id_1)
117+
_delete_catalog_slice(client, slice_id_2)
118+
_delete_catalog_slice(client, slice_id_2b)

0 commit comments

Comments
 (0)