Skip to content

Vb/merge 5.1.0 #1850

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
project = 'Python SDK reference'
copyright = '2024, Labelbox'
author = 'Labelbox'
release = '5.0.0'
release = '5.1.0'

# -- General configuration ---------------------------------------------------

Expand Down
5 changes: 5 additions & 0 deletions libs/labelbox/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# Changelog
# Version 5.1.0 (2024-09-27)
## Fixed
* Support self-signed SSL certs([#1811](https://github.com/Labelbox/labelbox-python/pull/1811))
* Rectangle units now correctly support percent inputs([#1848](https://github.com/Labelbox/labelbox-python/pull/1848))

# Version 5.0.0 (2024-09-16)
## Updated
* Set tasks_remaining_count to None LabelingServiceDashboard if labeling has not started ([#1817](https://github.com/Labelbox/labelbox-python/pull/1817))
Expand Down
2 changes: 1 addition & 1 deletion libs/labelbox/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "labelbox"
version = "5.0.0"
version = "5.1.0"
description = "Labelbox Python API"
authors = [{ name = "Labelbox", email = "engineering@labelbox.com" }]
dependencies = [
Expand Down
2 changes: 1 addition & 1 deletion libs/labelbox/src/labelbox/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "labelbox"

__version__ = "5.0.0"
__version__ = "5.1.0"

from labelbox.client import Client
from labelbox.schema.project import Project
Expand Down
2 changes: 1 addition & 1 deletion libs/labelbox/src/labelbox/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
import time
import urllib.parse
from collections import defaultdict
from datetime import datetime, timezone
from types import MappingProxyType
from typing import Any, Callable, Dict, List, Optional, Set, Union, overload

import lbox.exceptions
import requests
import requests.exceptions
from google.api_core import retry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class RectangleUnit(Enum):
INCHES = "INCHES"
PIXELS = "PIXELS"
POINTS = "POINTS"
PERCENT = "PERCENT"


class DocumentRectangle(Rectangle):
Expand Down
20 changes: 20 additions & 0 deletions libs/labelbox/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,21 @@ def teardown_ontology_feature_schemas(ontology: Ontology):
class ModuleTearDownHelpers(TearDownHelpers): ...


class LabelHelpers:
def wait_for_labels(self, project, number_of_labels=1):
timeout_seconds = 10
while True:
labels = list(project.labels())
if len(labels) >= number_of_labels:
return labels
timeout_seconds -= 2
if timeout_seconds <= 0:
raise TimeoutError(
f"Timed out waiting for label for project '{project.uid}' to finish processing"
)
time.sleep(2)


@pytest.fixture
def teardown_helpers():
return TearDownHelpers()
Expand All @@ -1256,3 +1271,8 @@ def teardown_helpers():
@pytest.fixture(scope="module")
def module_teardown_helpers():
return TearDownHelpers()


@pytest.fixture
def label_helpers():
return LabelHelpers()
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import datetime
import itertools
import uuid

import pytest

import labelbox as lb
from labelbox import Client, OntologyKind, Project
from labelbox.data.annotation_types import Label
from labelbox.data.annotation_types.data.generic_data_row_data import (
GenericDataRowData,
)
from labelbox.data.serialization.ndjson.converter import NDJsonConverter
from labelbox.data.annotation_types import Label
import pytest
import uuid

import labelbox as lb
from labelbox.schema.media_type import MediaType
from labelbox.schema.annotation_import import AnnotationImportState
from labelbox import Project, Client, OntologyKind
import itertools
from labelbox.schema.media_type import MediaType

"""
- integration test for importing mal labels and ground truths with each supported MediaType.
Expand Down Expand Up @@ -39,11 +40,6 @@ def validate_iso_format(date_string: str):
(MediaType.Conversational, MediaType.Conversational),
(MediaType.Document, MediaType.Document),
(MediaType.Dicom, MediaType.Dicom),
(
MediaType.LLMPromptResponseCreation,
MediaType.LLMPromptResponseCreation,
),
(MediaType.LLMPromptCreation, MediaType.LLMPromptCreation),
(OntologyKind.ResponseCreation, OntologyKind.ResponseCreation),
(OntologyKind.ModelEvaluation, OntologyKind.ModelEvaluation),
],
Expand All @@ -57,6 +53,7 @@ def test_import_media_types(
export_v2_test_helpers,
helpers,
media_type,
wait_for_label_processing,
):
annotations_ndjson = list(
itertools.chain.from_iterable(annotations_by_media_type[media_type])
Expand All @@ -73,6 +70,8 @@ def test_import_media_types(
assert label_import.state == AnnotationImportState.FINISHED
assert len(label_import.errors) == 0

wait_for_label_processing(configured_project)[0]

result = export_v2_test_helpers.run_project_export_v2_task(
configured_project
)
Expand Down Expand Up @@ -110,6 +109,53 @@ def test_import_media_types(
assert exported_annotations == expected_data


@pytest.mark.parametrize(
"configured_project, media_type",
[
(
MediaType.LLMPromptResponseCreation,
MediaType.LLMPromptResponseCreation,
),
(MediaType.LLMPromptCreation, MediaType.LLMPromptCreation),
],
indirect=["configured_project"],
)
def test_import_media_types_llm(
client: Client,
configured_project: Project,
annotations_by_media_type,
exports_v2_by_media_type,
export_v2_test_helpers,
helpers,
media_type,
wait_for_label_processing,
):
annotations_ndjson = list(
itertools.chain.from_iterable(annotations_by_media_type[media_type])
)

label_import = lb.LabelImport.create_from_objects(
client,
configured_project.uid,
f"test-import-{media_type}",
annotations_ndjson,
)
label_import.wait_until_done()

assert label_import.state == AnnotationImportState.FINISHED
assert len(label_import.errors) == 0

all_annotations = sorted([a["uuid"] for a in annotations_ndjson])
successful_annotations = sorted(
[
status["uuid"]
for status in label_import.statuses
if status["status"] == "SUCCESS"
]
)
assert successful_annotations == all_annotations


@pytest.mark.parametrize(
"configured_project_by_global_key, media_type",
[
Expand Down
20 changes: 2 additions & 18 deletions libs/labelbox/tests/integration/schema/test_user_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,35 +147,19 @@ def test_cannot_update_group_id(user_group):
def test_get_user_groups_with_creation_deletion(client):
user_group = None
try:
# Get all user groups
user_groups = list(UserGroup(client).get_user_groups())

# manual delete for iterators
group_name = data.name()
user_group = UserGroup(client)
user_group.name = group_name
user_group.create()

user_groups_post_creation = list(UserGroup(client).get_user_groups())
assert user_group in user_groups_post_creation

# Verify that at least one user group is returned
assert len(user_groups_post_creation) > 0
assert len(user_groups_post_creation) == len(user_groups) + 1

# Verify that each user group has a valid ID and name
for ug in user_groups_post_creation:
assert ug.id is not None
assert ug.name is not None

user_group.delete()
user_group = None

user_groups_post_deletion = list(UserGroup(client).get_user_groups())

assert (
len(user_groups_post_deletion) == len(user_groups_post_creation) - 1
)

assert user_group not in user_groups_post_deletion
finally:
if user_group:
user_group.delete()
Expand Down
4 changes: 3 additions & 1 deletion libs/labelbox/tests/integration/test_label.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ def test_label_update(configured_project_with_label):
assert label.label == "something else"


def test_label_filter_order(configured_project_with_label):
def test_label_filter_order(configured_project_with_label, label_helpers):
project, _, _, label = configured_project_with_label

l1 = label
project.create_label()
label_helpers.wait_for_labels(project, 2)

l2 = next(project.labels())

assert set(project.labels()) == {l1, l2}
Expand Down
6 changes: 3 additions & 3 deletions libs/labelbox/tests/integration/test_labeling_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pytest
from lbox.exceptions import LabelboxError, ResourceNotFoundError
from lbox.exceptions import MalformedQueryException, ResourceNotFoundError

from labelbox.schema.labeling_service import LabelingServiceStatus

Expand Down Expand Up @@ -51,7 +51,7 @@ def test_request_labeling_service_moe_project(

labeling_service = project.get_labeling_service()
with pytest.raises(
LabelboxError,
MalformedQueryException,
match='[{"errorType":"PROJECT_MODEL_CONFIG","errorMessage":"Project model config is not completed"}]',
):
labeling_service.request()
Expand All @@ -73,5 +73,5 @@ def test_request_labeling_service_incomplete_requirements(ontology, project):
): # No labeling service by default
labeling_service.request()
project.connect_ontology(ontology)
with pytest.raises(LabelboxError):
with pytest.raises(MalformedQueryException):
labeling_service.request()
7 changes: 6 additions & 1 deletion libs/lbox-clients/src/lbox/request_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,12 @@ def convert_value(value):

prepped: requests.PreparedRequest = request.prepare()

response = self._connection.send(prepped, timeout=timeout)
settings = self._connection.merge_environment_settings(
prepped.url, {}, None, None, None
)
response = self._connection.send(
prepped, timeout=timeout, **settings
)
logger.debug("Response: %s", response.text)
except requests.exceptions.Timeout as e:
raise exceptions.TimeoutError(str(e))
Expand Down
Loading