Skip to content

Commit 0b147d4

Browse files
authored
chore: example util function to construct studio url (#780)
* example on constructing studio url with simple filter * trim comments * trim dep * add ci
1 parent e874783 commit 0b147d4

File tree

6 files changed

+177
-1
lines changed

6 files changed

+177
-1
lines changed

.circleci/continue_config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ workflows:
439439
- aws
440440
matrix:
441441
parameters:
442-
subproject: [ age_estimation, automatic_speech_recognition, classification, keypoint_detection, question_answering, rain_forecast, semantic_segmentation, speaker_diarization, semantic_textual_similarity, person_detection, crossing_pedestrian_detection, named_entity_recognition ]
442+
subproject: [ age_estimation, automatic_speech_recognition, classification, keypoint_detection, question_answering, rain_forecast, semantic_segmentation, speaker_diarization, semantic_textual_similarity, person_detection, crossing_pedestrian_detection, named_entity_recognition, construct_studio_url ]
443443
resource-class: [ small ]
444444
python-version: [ "3.9.18" ]
445445
- example-test-workflow:
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Example
2+
3+
Construct a Studio URL from dataset information. Example:
4+
5+
```python
6+
from construct_studio_url.encode_url import construct_studio_url
7+
8+
tenant = "my-organization"
9+
dataset_id = 123
10+
datapoint_field = "locator"
11+
value = "s3://my-bucket/image_001.jpg"
12+
13+
print(construct_studio_url(tenant, dataset_id, datapoint_field, value))
14+
```
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2021-2025 Kolena Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Copyright 2021-2025 Kolena Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import json
15+
from urllib.parse import quote
16+
17+
import lzstring
18+
19+
20+
def construct_studio_url(tenant: str, dataset_id: int, datapoint_field: str, value: str) -> str:
21+
"""
22+
Generate a Kolena dataset studio URL with a filter applied.
23+
24+
Args:
25+
tenant: The tenant name (e.g., "try")
26+
dataset_id: The ID of the dataset (e.g., 59)
27+
datapoint_field: The field name to filter on (e.g., "uuid")
28+
value: The value to filter for (e.g., "abc")
29+
Returns:
30+
A fully formatted URL string with the filter encoded
31+
"""
32+
field_name = f"datapoint.{datapoint_field}"
33+
filter_data = {
34+
"contains": value,
35+
"options": {
36+
"regex_match": False,
37+
"regex_flags": "",
38+
"inverse": False,
39+
},
40+
}
41+
json_string = json.dumps(filter_data, separators=(",", ":"))
42+
43+
compressor = lzstring.LZString()
44+
compressed = compressor.compressToEncodedURIComponent(json_string)
45+
filter_string = f"{field_name}:{compressed}:c"
46+
encoded_filter = quote(filter_string, safe="")
47+
48+
base_url = f"https://app.kolena.com/{tenant}/dataset/studio"
49+
full_url = f"{base_url}?datasetId={dataset_id}&filters={encoded_filter}"
50+
51+
return full_url
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[project]
2+
name = "construct_studio_url"
3+
version = "0.1.0"
4+
description = "Example generating Kolena studio URL with simple filters"
5+
authors = [
6+
{ name = "Kolena Engineering", email = "eng@kolena.com" }
7+
]
8+
license = "Apache-2.0"
9+
requires-python = ">=3.9,<3.12"
10+
11+
dependencies = [
12+
"lzstring>=1",
13+
]
14+
15+
[tool.uv]
16+
dev-dependencies = [
17+
"pre-commit>=2.17,<3",
18+
"pytest>=7,<8",
19+
"pytest-depends>=1.0.1,<2",
20+
]
21+
22+
[build-system]
23+
requires = ["hatchling"]
24+
build-backend = "hatchling.build"
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Copyright 2021-2025 Kolena Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import pytest
15+
from construct_studio_url.encode_url import construct_studio_url
16+
17+
18+
@pytest.mark.parametrize(
19+
"tenant,dataset_id,datapoint_field,value,expected_url",
20+
[
21+
(
22+
"try",
23+
14,
24+
"locator",
25+
"s3://kolena-public-examples/coco-2014-val/data/COCO_val2014_000000000074.jpg",
26+
"https://app.kolena.com/try/dataset/studio?datasetId=14&filters=datapoint.locator%3AN4Igxg9gdgLghgSygZxALhMgzGg9LgawgBsBTKOAWgAcBXAI2ITEtIA84Bbas5XSSJQBMABgCMAFkoA3OMVwATOPFwBhAPIaA%2BrOKjJWkUeMmA7BIB0AK2oBzEABoQEajATRUaUACdSt9lqcymAAFugAZnLIpE6%2B-mxa4cRwtp4gjiBI0qTe0RFRpAC%2BhUA%3Ac", # noqa: E501
27+
),
28+
(
29+
"try",
30+
45,
31+
"date_captured",
32+
"2013-11-16 12:50:10",
33+
"https://app.kolena.com/try/dataset/studio?datasetId=45&filters=datapoint.date_captured%3AN4Igxg9gdgLghgSygZxALhAJgAwEYDMAtLrsQGwAEumaArNmrtiADQgQAOMC0qaoAJwCmAcyEAPAPoBbODDAALdADM4AG2RC2wsVOVq4IviFYgkANyEDNK9ZoC%2B9oA%3Ac", # noqa: E501
34+
),
35+
(
36+
"try",
37+
21,
38+
"Location",
39+
"Richmond",
40+
"https://app.kolena.com/try/dataset/studio?datasetId=21&filters=datapoint.Location%3AN4Igxg9gdgLghgSygZxALhAJQWAFgW2gBMQAaECABxgWlTVACcBTAc2YA8B9fOGPdADM4AG2TNyLdt0Ei4reiDIgkAN2aNxQ0eIC%2BuoA%3Ac", # noqa: E501
41+
),
42+
(
43+
"try",
44+
19,
45+
"transcription_path",
46+
"audio/Bed017/interval3.csv",
47+
"https://app.kolena.com/try/dataset/studio?datasetId=19&filters=datapoint.transcription_path%3AN4Igxg9gdgLghgSygZxALhHArgEwRAegCEBTHABgEYB2ApGEgJwDc4AbAZgDoxlmQANCAgAHGPhTpQjEgHMSADwD6AWzgwwAC3QAzdshJCZ85TrZxZqDIJBJmTA7v0kAvi6A%3Ac", # noqa: E501
48+
),
49+
(
50+
"try",
51+
25,
52+
"abstract",
53+
"We propose a real-time method to estimate spatially-varying indoor lighting from a single RGB image. Given an image and a 2D location in that image, our CNN estimates a 5th order spherical harmonic representation of the lighting at the given location in less than 20ms on a laptop mobile graphics card. While existing approaches estimate a single, global lighting representation or require depth as input, our method reasons about local lighting without requiring any geometry information. We demonstrate, through quantitative experiments including a user study, that our results achieve lower lighting estimation errors and are preferred by users over the state-of-the-art. Our approach can be used directly for augmented reality applications, where a virtual object is relit realistically at any position in the scene in real-time.", # noqa: E501
54+
"https://app.kolena.com/try/dataset/studio?datasetId=25&filters=datapoint.abstract%3AN4Igxg9gdgLghgSygZxALhAdQKYAIAOAThPhMnnLodnADYC0MCAtnqzABYQAmuMEubMibM4MPMnxiEdWgE96ANziE5SAOa4k3CBEK5aCdRyZRNAM2LNclZBtp4ASgHEAQltHrsAOlzOEithQNsEscF4hvJQATAAiBhBg0tBawZxiHuHYADS4EACu%2BgDCAHIlgsJh4sg2uACsnHmE3Nj6khytCEm0uBwqzNBdVNhEQkHwTCkQ5nwdBkYmGjYws3jqAUEJSZOhwQ7INenB0QAMzDUplLRw%2BPz4uAMARggOuOqENxxdNUnNvphfV7YAAeCEqZhs%2BCIEDgYA6NSEIjEFFwdjMDly6loEEedHmxlMmmoo3IsGSwT0wwAjvkENRcC1bhwbDUkPh8jBcgV9OwuLxqHBkNAanBHgUVtjuvjFhCAO4ITji6m0whLOBQORvbAQdiqVLmPSiHb-PAtAYoGAfcS5TjEfLGXA09VMCYbQTA-CdViwVlQMC0fLcNW4fLkNowQNyG19Fbc4bIfK0GAiuEIbCBBKy1rSwkVJE7QSEYiEEVQKL00bmVrUXiPTWh1oXQL6TgSCbYejTRgdegqGC%2BADyhUh0NhzKSwUeeAbvCD1DAMHkuAN%2Bjg9u94n5NEMME1N3whm2CGFuVlHXplEUdIjeJxACtsAutDVqDvhnQwUxukuMurNaQ7ALJBVlRMAgjwYCBQYEQfBAbIQBIHZUDQUBqC8YEAH0jThdBzDoch4LQkEMPMa51GQkA4JAJBm3IXD8OwABfRigA%3Ac", # noqa: E501
55+
),
56+
(
57+
"demo",
58+
165,
59+
"text_summary",
60+
"Andras Janos Vass, 25, found guilty of human trafficking and racketeering. Lured at least two young men to America via Planet Romeo dating site. Thought they would be offered legal escort work, earning $5,000 a month. Victims said they had travel documents taken and were forced into sex. Vass's sex ring, which he allegedly ran with two other men, started in NYC. Moved to Miami in late 2012, where Vass has been standing trial. He faces up to 155 years in prison for his crime - with minimum of 21 years.", # noqa: E501
61+
"https://app.kolena.com/demo/dataset/studio?datasetId=165&filters=datapoint.text_summary%3AN4Igxg9gdgLghgSygZxALhAQSgEwE5zIAEAUnFBMQGqHIA0RATAKwMBmEArrkQOacIANjACeRCGyIALTgFtyRGATZsEYANZJeRcjiIENAUxiHDeLQDoiAGU55DeuDCKDDhZzADuEIiK5RtWUMoRR9MIPMwOCIANwRogAVBcmMiACUIIJ8cJy0iZAQTKwAVKS5eKQ8pQzFvTkE9ACNDcRUzBxdDXjhBIkNkSDxnbzx1Bjc8KDyAElYABgWdIlloGCkrKjUYBFliZEQ9NZrpOEOCGMNenAgwOWCYYnh1YJ0eT3aiDjwwDqQYH2QhgAHhtaAByPbA-RaBieKRqKTSFo9Vy8ByCMQEEKeQqIrw%2BCBHPDLYIMZDwIa-EIAOQAmgBhKwAWQgF0OPiZ8VkCCISBcThajDmAEZGLDqvYiDRkMQpIQiM0XuTdHklPFBFYABItNhwH7ETgAB1CRGFzGYvgmxD5hvMyGgnwgxPhxDA5iCRAAtEQcWtlkgdnJWkxhZa4HhkBYQHQQBBDdtoKg0KB7GigQB9eQwMBSdC6wSAmOp4HptjJXhJkDRkBIC4Rwx5nqAgC%2BzaAA%3Ac", # noqa: E501
62+
),
63+
],
64+
)
65+
def test__construct_studio_url(
66+
tenant: str,
67+
dataset_id: int,
68+
datapoint_field: str,
69+
value: str,
70+
expected_url: str,
71+
) -> None:
72+
generated = construct_studio_url(tenant, dataset_id, datapoint_field, value)
73+
print(generated)
74+
assert generated == expected_url

0 commit comments

Comments
 (0)