Skip to content

Commit 6369334

Browse files
authored
Merge branch 'develop' into pno/PLT-2447-update_connect_ontology
2 parents a5892ba + c5025f1 commit 6369334

File tree

23 files changed

+1237
-50
lines changed

23 files changed

+1237
-50
lines changed

.github/workflows/python-package-develop.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,15 @@ jobs:
6161
- python-version: "3.9"
6262
api-key: STAGING_LABELBOX_API_KEY_3
6363
da-test-key: DA_GCP_LABELBOX_API_KEY
64-
sdk-version: ${{ fromJson(needs.get_sdk_versions.outputs.sdk_versions)[3] }}
6564
- python-version: "3.10"
6665
api-key: STAGING_LABELBOX_API_KEY_4
6766
da-test-key: DA_GCP_LABELBOX_API_KEY
68-
sdk-version: ${{ fromJson(needs.get_sdk_versions.outputs.sdk_versions)[2] }}
6967
- python-version: "3.11"
7068
api-key: STAGING_LABELBOX_API_KEY
7169
da-test-key: DA_GCP_LABELBOX_API_KEY
72-
sdk-version: ${{ fromJson(needs.get_sdk_versions.outputs.sdk_versions)[1] }}
7370
- python-version: "3.12"
7471
api-key: STAGING_LABELBOX_API_KEY_5
75-
da-test-key: DA_GCP_LABELBOX_API_KEY
76-
sdk-version: ${{ fromJson(needs.get_sdk_versions.outputs.sdk_versions)[0] }}
72+
da-test-key: DA_GCP_LABELBOX_API_KEY
7773
- python-version: "3.13"
7874
api-key: STAGING_LABELBOX_API_KEY_2
7975
da-test-key: DA_GCP_LABELBOX_API_KEY

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
project = 'Python SDK reference'
1717
copyright = '2025, Labelbox'
1818
author = 'Labelbox'
19-
release = '6.8.0'
19+
release = '6.10.0'
2020

2121
# -- General configuration ---------------------------------------------------
2222

libs/labelbox/CHANGELOG.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
11
# Changelog
2-
Version 6.8.0 (2025-02-20)
3-
### Added Support for Source Ontology Names in Relationships
2+
# Version 6.10.0 (2025-04-04)
3+
## Added
4+
* API keys Management: ([#1961](https://github.com/Labelbox/labelbox-python/pull/1961))
5+
* Get invitations: ([#1962](https://github.com/Labelbox/labelbox-python/pull/1962))
6+
* Add tasks to organization and TaskStatus to filter tasks: ([#1958](https://github.com/Labelbox/labelbox-python/pull/1958))
7+
8+
9+
# Version 6.9.0 (2025-03-17)
10+
## Added
11+
* Provide support to cancel tasks ([#1957](https://github.com/Labelbox/labelbox-python/pull/1957))
12+
* Added support for AUDIO attachment type ([#1956](https://github.com/Labelbox/labelbox-python/pull/1956))
13+
14+
# Version 6.8.0 (2025-02-20)
15+
## Added Support for Source Ontology Names in Relationships
416

517
Added the ability to specify relationships using `source_ontology_name` instead of a concrete source annotation. This enhancement is particularly useful for PDF document annotations where you can create relationships referencing ontology classes directly.
618

719
Key changes:
820
- Added optional `source_ontology_name` field to `Relationship` class
921
- Made `source` field optional
1022
- Added validation to ensure either `source` or `source_ontology_name` is provided, but not both
11-
### Added search by name for `get_catalog_slice`
12-
### Added `get_catalog_slices` to get all slices
23+
## Added search by name for `get_catalog_slice`
24+
## Added `get_catalog_slices` to get all slices
1325

1426
# Version 6.7.0 (2025-02-06)
1527
## Added

libs/labelbox/pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "labelbox"
3-
version = "6.8.0"
3+
version = "6.10.0"
44
description = "Labelbox Python API"
55
authors = [{ name = "Labelbox", email = "engineering@labelbox.com" }]
66
dependencies = [
@@ -11,7 +11,6 @@ dependencies = [
1111
"strenum>=0.4.15",
1212
"tqdm>=4.66.2",
1313
"geojson>=3.1.0",
14-
"mypy==1.10.1",
1514
"lbox-clients==1.1.2",
1615
]
1716
readme = "README.md"

libs/labelbox/src/labelbox/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "labelbox"
22

3-
__version__ = "6.8.0"
3+
__version__ = "6.10.0"
44

55
from labelbox.client import Client
66
from labelbox.schema.annotation_import import (
@@ -98,3 +98,6 @@
9898
PromptResponseClassification,
9999
)
100100
from lbox.exceptions import *
101+
from labelbox.schema.taskstatus import TaskStatus
102+
from labelbox.schema.api_key import ApiKey
103+
from labelbox.schema.timeunit import TimeUnit

libs/labelbox/src/labelbox/client.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@
7979
from labelbox.schema.slice import CatalogSlice, ModelSlice
8080
from labelbox.schema.task import DataUpsertTask, Task
8181
from labelbox.schema.user import User
82+
from labelbox.schema.taskstatus import TaskStatus
83+
from labelbox.schema.api_key import ApiKey
84+
from labelbox.schema.timeunit import TimeUnit
8285

8386
logger = logging.getLogger(__name__)
8487

@@ -90,6 +93,9 @@ class Client:
9093
top-level data objects (Projects, Datasets).
9194
"""
9295

96+
# Class variable to cache task types
97+
_cancelable_task_types = None
98+
9399
def __init__(
94100
self,
95101
api_key=None,
@@ -2389,3 +2395,124 @@ def get_task_by_id(self, task_id: str) -> Union[Task, DataUpsertTask]:
23892395

23902396
task._user = user
23912397
return task
2398+
2399+
def _get_cancelable_task_types(self):
2400+
"""Internal method that returns a list of task types that can be canceled.
2401+
2402+
The result is cached after the first call to avoid unnecessary API requests.
2403+
2404+
Returns:
2405+
List[str]: List of cancelable task types in snake_case format
2406+
"""
2407+
if self._cancelable_task_types is None:
2408+
query = """query GetCancelableTaskTypesPyApi {
2409+
cancelableTaskTypes
2410+
}"""
2411+
2412+
result = self.execute(query).get("cancelableTaskTypes", [])
2413+
# Reformat to kebab case
2414+
self._cancelable_task_types = [
2415+
utils.snake_case(task_type).replace("_", "-")
2416+
for task_type in result
2417+
]
2418+
2419+
return self._cancelable_task_types
2420+
2421+
def cancel_task(self, task_id: str) -> bool:
2422+
"""
2423+
Cancels a task with the given ID if the task type is cancelable and the task is in progress.
2424+
2425+
Args:
2426+
task_id (str): The ID of the task to cancel.
2427+
2428+
Returns:
2429+
bool: True if the task was successfully cancelled.
2430+
2431+
Raises:
2432+
LabelboxError: If the task could not be cancelled, if the task type is not cancelable,
2433+
or if the task is not in progress.
2434+
ResourceNotFoundError: If the task does not exist (raised by get_task_by_id).
2435+
"""
2436+
# Get the task object to check its type and status
2437+
task = self.get_task_by_id(task_id)
2438+
2439+
# Check if task type is cancelable
2440+
cancelable_types = self._get_cancelable_task_types()
2441+
if task.type not in cancelable_types:
2442+
raise LabelboxError(
2443+
f"Task type '{task.type}' cannot be cancelled. Cancelable types are: {cancelable_types}"
2444+
)
2445+
2446+
# Check if task is in progress
2447+
if task.status_as_enum != TaskStatus.In_Progress:
2448+
raise LabelboxError(
2449+
f"Task cannot be cancelled because it is not in progress. Current status: {task.status}"
2450+
)
2451+
2452+
mutation_str = """
2453+
mutation CancelTaskPyApi($id: ID!) {
2454+
cancelBulkOperationJob(id: $id) {
2455+
success
2456+
}
2457+
}
2458+
"""
2459+
res = self.execute(mutation_str, {"id": task_id})
2460+
return res["cancelBulkOperationJob"]["success"]
2461+
2462+
def create_api_key(
2463+
self,
2464+
name: str,
2465+
user: Union[User, str],
2466+
role: Union[Role, str],
2467+
validity: int = 0,
2468+
time_unit: TimeUnit = TimeUnit.SECOND,
2469+
refresh_cache: bool = False,
2470+
) -> Dict[str, str]:
2471+
"""Creates a new API key.
2472+
2473+
Args:
2474+
name (str): The name of the API key.
2475+
user (Union[User, str]): The user object or user ID to associate with the API key.
2476+
role (Union[Role, str]): The role object or role ID to assign to the API key.
2477+
validity (int, optional): The validity period of the API key. Defaults to 0 (no expiration).
2478+
time_unit (TimeUnit, optional): The time unit for the validity period. Defaults to TimeUnit.SECOND.
2479+
refresh_cache (bool, optional): Whether to refresh cached permissions and roles. Defaults to False.
2480+
2481+
Returns:
2482+
Dict[str, str]: A dictionary containing the created API key information.
2483+
"""
2484+
warnings.warn(
2485+
"The creation of API keys is currently in alpha and its behavior may change in future releases.",
2486+
)
2487+
if refresh_cache:
2488+
# Clear cached attributes if they exist
2489+
if hasattr(self, "_cached_current_user_permissions"):
2490+
delattr(self, "_cached_current_user_permissions")
2491+
if hasattr(self, "_cached_available_api_key_roles"):
2492+
delattr(self, "_cached_available_api_key_roles")
2493+
2494+
return ApiKey.create_api_key(
2495+
self, name, user, role, validity, time_unit
2496+
)
2497+
2498+
def get_api_keys(self, include_expired: bool = False) -> List[ApiKey]:
2499+
"""Retrieves all API keys accessible to the current user.
2500+
2501+
Args:
2502+
include_revoked (bool, optional): Whether to include revoked API keys. Defaults to True.
2503+
2504+
Returns:
2505+
List[ApiKey]: A list of ApiKey objects.
2506+
"""
2507+
return ApiKey.get_api_keys(self, include_expired)
2508+
2509+
def get_api_key(self, api_key_id: str) -> Optional[ApiKey]:
2510+
"""Retrieves a single API key by its ID.
2511+
2512+
Args:
2513+
api_key_id (str): The unique ID of the API key.
2514+
2515+
Returns:
2516+
Optional[ApiKey]: The corresponding ApiKey object if found, otherwise None.
2517+
"""
2518+
return ApiKey.get_api_key(self, api_key_id)

libs/labelbox/src/labelbox/orm/model.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ class Field:
2929
These `Comparison` objects can then be used for filtering:
3030
>>> project = client.get_projects(comparison)
3131
32-
Also exposes the ordering property used for sorting:
33-
>>> labels = project.labels(order_by=Label.label.asc)
34-
3532
Attributes:
3633
field_type (Field.Type): The type of the field.
3734
name (str): name that the attribute has in client-side Python objects

libs/labelbox/src/labelbox/schema/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@
2626
import labelbox.schema.catalog
2727
import labelbox.schema.ontology_kind
2828
import labelbox.schema.project_overview
29+
import labelbox.schema.taskstatus
30+
import labelbox.schema.api_key
31+
import labelbox.schema.timeunit

0 commit comments

Comments
 (0)