Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
42f53d5
Adds sdk label support for multiclass detectors
Dec 4, 2024
4097ec9
Automatically reformatting code
Dec 4, 2024
24a0c4a
fixing comments
Dec 4, 2024
862b652
Merge branch 'multiclass_label_support' of github.com:groundlight/pyt…
Dec 4, 2024
71e2fa4
Merge branch 'main' into multiclass_label_support
Dec 6, 2024
bf39741
Allows for filtering by detector_id
Dec 10, 2024
eee8808
linter love
Dec 10, 2024
10e8dcc
equivilent-ish exchange of pylint disables
Dec 10, 2024
81f6822
Automatically reformatting code
Dec 10, 2024
1671f38
Merge branch 'main' into multiclass_label_support
Dec 10, 2024
c4106a4
fix class_name
Dec 10, 2024
7000867
Merge branch 'multiclass_label_support' of github.com:groundlight/pyt…
Dec 10, 2024
752a52b
manually reverting a bad merge
Dec 10, 2024
a53cdb8
Automatically reformatting code
Dec 10, 2024
fb06067
!! Removing client side label checking. Among the various detector mo…
Dec 10, 2024
4da2633
Merge branch 'multiclass_label_support' of github.com:groundlight/pyt…
Dec 10, 2024
3309830
Automatically reformatting code
Dec 10, 2024
fbf3fbb
!! add back in as much type checking as we can now
Dec 10, 2024
f6f2127
Merge branch 'multiclass_label_support' of github.com:groundlight/pyt…
Dec 10, 2024
9b07cf5
Automatically reformatting code
Dec 10, 2024
1e9ac4e
remove debugging line
Dec 10, 2024
b0e6ccb
Merge branch 'multiclass_label_support' of github.com:groundlight/pyt…
Dec 10, 2024
790dcdd
linter suggestions
Dec 10, 2024
ed3fe0c
Automatically reformatting code
Dec 10, 2024
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 .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ disable=raw-checker-failed,
missing-class-docstring,
missing-function-docstring,
invalid-name,
too-few-public-methods,
line-too-long,
import-error, # we only install linter dependencies in CI/CD
wrong-import-order, # we use ruff to enforce import order
duplicate-code, # pylint has a tendancy to capture docstrings as duplicate code


# Enable the message, report, category or checker with the given id(s). You can
Expand Down
4 changes: 3 additions & 1 deletion generated/docs/ImageQueriesApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,12 @@ with groundlight_openapi_client.ApiClient(configuration) as api_client:
api_instance = image_queries_api.ImageQueriesApi(api_client)
page = 1 # int | A page number within the paginated result set. (optional)
page_size = 1 # int | Number of items to return per page. (optional)
predictor_id = "predictor_id_example" # str | Optionally filter image queries by detector ID. (optional)

# example passing only required values which don't have defaults set
# and optional values
try:
api_response = api_instance.list_image_queries(page=page, page_size=page_size)
api_response = api_instance.list_image_queries(page=page, page_size=page_size, predictor_id=predictor_id)
pprint(api_response)
except groundlight_openapi_client.ApiException as e:
print("Exception when calling ImageQueriesApi->list_image_queries: %s\n" % e)
Expand All @@ -220,6 +221,7 @@ Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**page** | **int**| A page number within the paginated result set. | [optional]
**page_size** | **int**| Number of items to return per page. | [optional]
**predictor_id** | **str**| Optionally filter image queries by detector ID. | [optional]

### Return type

Expand Down
5 changes: 5 additions & 0 deletions generated/groundlight_openapi_client/api/image_queries_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ def __init__(self, api_client=None):
"all": [
"page",
"page_size",
"predictor_id",
],
"required": [],
"nullable": [],
Expand All @@ -141,14 +142,17 @@ def __init__(self, api_client=None):
"openapi_types": {
"page": (int,),
"page_size": (int,),
"predictor_id": (str,),
},
"attribute_map": {
"page": "page",
"page_size": "page_size",
"predictor_id": "predictor_id",
},
"location_map": {
"page": "query",
"page_size": "query",
"predictor_id": "query",
},
"collection_format_map": {},
},
Expand Down Expand Up @@ -375,6 +379,7 @@ def list_image_queries(self, **kwargs):
Keyword Args:
page (int): A page number within the paginated result set.. [optional]
page_size (int): Number of items to return per page.. [optional]
predictor_id (str): Optionally filter image queries by detector ID.. [optional]
_return_http_data_only (bool): response data without head status
code and headers. Default is True.
_preload_content (bool): if False, the urllib3.HTTPResponse object
Expand Down
151 changes: 93 additions & 58 deletions generated/groundlight_openapi_client/model/patched_detector_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
Generated by: https://openapi-generator.tech
"""


import re # noqa: F401
import sys # noqa: F401

Expand All @@ -25,7 +24,7 @@
file_type,
none_type,
validate_get_composed_info,
OpenApiModel
OpenApiModel,
)
from groundlight_openapi_client.exceptions import ApiAttributeError

Expand All @@ -34,9 +33,10 @@ def lazy_import():
from groundlight_openapi_client.model.blank_enum import BlankEnum
from groundlight_openapi_client.model.escalation_type_enum import EscalationTypeEnum
from groundlight_openapi_client.model.status_enum import StatusEnum
globals()['BlankEnum'] = BlankEnum
globals()['EscalationTypeEnum'] = EscalationTypeEnum
globals()['StatusEnum'] = StatusEnum

globals()["BlankEnum"] = BlankEnum
globals()["EscalationTypeEnum"] = EscalationTypeEnum
globals()["StatusEnum"] = StatusEnum


class PatchedDetectorRequest(ModelNormal):
Expand All @@ -63,21 +63,20 @@ class PatchedDetectorRequest(ModelNormal):
as additional properties values.
"""

allowed_values = {
}
allowed_values = {}

validations = {
('name',): {
'max_length': 200,
'min_length': 1,
("name",): {
"max_length": 200,
"min_length": 1,
},
('confidence_threshold',): {
'inclusive_maximum': 1.0,
'inclusive_minimum': 0.0,
("confidence_threshold",): {
"inclusive_maximum": 1.0,
"inclusive_minimum": 0.0,
},
('patience_time',): {
'inclusive_maximum': 3600,
'inclusive_minimum': 0,
("patience_time",): {
"inclusive_maximum": 3600,
"inclusive_minimum": 0,
},
}

Expand All @@ -88,7 +87,17 @@ def additional_properties_type():
of type self, this must run after the class is loaded
"""
lazy_import()
return (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501
return (
bool,
date,
datetime,
dict,
float,
int,
list,
str,
none_type,
) # noqa: E501

_nullable = False

Expand All @@ -104,28 +113,46 @@ def openapi_types():
"""
lazy_import()
return {
'name': (str,), # noqa: E501
'confidence_threshold': (float,), # noqa: E501
'patience_time': (float,), # noqa: E501
'status': (bool, date, datetime, dict, float, int, list, str, none_type,), # noqa: E501
'escalation_type': (bool, date, datetime, dict, float, int, list, str, none_type,), # noqa: E501
"name": (str,), # noqa: E501
"confidence_threshold": (float,), # noqa: E501
"patience_time": (float,), # noqa: E501
"status": (
bool,
date,
datetime,
dict,
float,
int,
list,
str,
none_type,
), # noqa: E501
"escalation_type": (
bool,
date,
datetime,
dict,
float,
int,
list,
str,
none_type,
), # noqa: E501
}

@cached_property
def discriminator():
return None


attribute_map = {
'name': 'name', # noqa: E501
'confidence_threshold': 'confidence_threshold', # noqa: E501
'patience_time': 'patience_time', # noqa: E501
'status': 'status', # noqa: E501
'escalation_type': 'escalation_type', # noqa: E501
"name": "name", # noqa: E501
"confidence_threshold": "confidence_threshold", # noqa: E501
"patience_time": "patience_time", # noqa: E501
"status": "status", # noqa: E501
"escalation_type": "escalation_type", # noqa: E501
}

read_only_vars = {
}
read_only_vars = {}

_composed_schemas = {}

Expand Down Expand Up @@ -172,17 +199,18 @@ def _from_openapi_data(cls, *args, **kwargs): # noqa: E501
escalation_type (bool, date, datetime, dict, float, int, list, str, none_type): Category that define internal proccess for labeling image queries * `STANDARD` - STANDARD * `NO_HUMAN_LABELING` - NO_HUMAN_LABELING. [optional] # noqa: E501
"""

_check_type = kwargs.pop('_check_type', True)
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
_path_to_item = kwargs.pop('_path_to_item', ())
_configuration = kwargs.pop('_configuration', None)
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
_check_type = kwargs.pop("_check_type", True)
_spec_property_naming = kwargs.pop("_spec_property_naming", False)
_path_to_item = kwargs.pop("_path_to_item", ())
_configuration = kwargs.pop("_configuration", None)
_visited_composed_classes = kwargs.pop("_visited_composed_classes", ())

self = super(OpenApiModel, cls).__new__(cls)

if args:
raise ApiTypeError(
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments."
% (
args,
self.__class__.__name__,
),
Expand All @@ -198,22 +226,24 @@ def _from_openapi_data(cls, *args, **kwargs): # noqa: E501
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)

for var_name, var_value in kwargs.items():
if var_name not in self.attribute_map and \
self._configuration is not None and \
self._configuration.discard_unknown_keys and \
self.additional_properties_type is None:
if (
var_name not in self.attribute_map
and self._configuration is not None
and self._configuration.discard_unknown_keys
and self.additional_properties_type is None
):
# discard variable.
continue
setattr(self, var_name, var_value)
return self

required_properties = set([
'_data_store',
'_check_type',
'_spec_property_naming',
'_path_to_item',
'_configuration',
'_visited_composed_classes',
"_data_store",
"_check_type",
"_spec_property_naming",
"_path_to_item",
"_configuration",
"_visited_composed_classes",
])

@convert_js_args_to_python_args
Expand Down Expand Up @@ -258,15 +288,16 @@ def __init__(self, *args, **kwargs): # noqa: E501
escalation_type (bool, date, datetime, dict, float, int, list, str, none_type): Category that define internal proccess for labeling image queries * `STANDARD` - STANDARD * `NO_HUMAN_LABELING` - NO_HUMAN_LABELING. [optional] # noqa: E501
"""

_check_type = kwargs.pop('_check_type', True)
_spec_property_naming = kwargs.pop('_spec_property_naming', False)
_path_to_item = kwargs.pop('_path_to_item', ())
_configuration = kwargs.pop('_configuration', None)
_visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
_check_type = kwargs.pop("_check_type", True)
_spec_property_naming = kwargs.pop("_spec_property_naming", False)
_path_to_item = kwargs.pop("_path_to_item", ())
_configuration = kwargs.pop("_configuration", None)
_visited_composed_classes = kwargs.pop("_visited_composed_classes", ())

if args:
raise ApiTypeError(
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
"Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments."
% (
args,
self.__class__.__name__,
),
Expand All @@ -282,13 +313,17 @@ def __init__(self, *args, **kwargs): # noqa: E501
self._visited_composed_classes = _visited_composed_classes + (self.__class__,)

for var_name, var_value in kwargs.items():
if var_name not in self.attribute_map and \
self._configuration is not None and \
self._configuration.discard_unknown_keys and \
self.additional_properties_type is None:
if (
var_name not in self.attribute_map
and self._configuration is not None
and self._configuration.discard_unknown_keys
and self.additional_properties_type is None
):
# discard variable.
continue
setattr(self, var_name, var_value)
if var_name in self.read_only_vars:
raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
f"class with read only attributes.")
raise ApiAttributeError(
f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
"class with read only attributes."
)
2 changes: 1 addition & 1 deletion generated/model.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# generated by datamodel-codegen:
# filename: public-api.yaml
# timestamp: 2024-12-09T18:29:17+00:00
# timestamp: 2024-12-10T01:13:13+00:00

from __future__ import annotations

Expand Down
22 changes: 0 additions & 22 deletions src/groundlight/binary_labels.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,3 @@ def convert_internal_label_to_display(

logger.warning(f"Unrecognized internal label {label} - leaving it alone as a string.")
return label


def convert_display_label_to_internal(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥳

context: Union[ImageQuery, Detector, str], # pylint: disable=unused-argument
label: Union[Label, str],
) -> str:
"""Convert a label that comes from the user into the label string that we send to the server. We
are strict here, and only allow YES/NO.

NOTE: We accept case-insensitive label strings from the user, but we send UPPERCASE labels to
the server. E.g., user inputs "yes" -> the label is returned as "YES".
"""
# NOTE: In the future we should validate against actually supported labels for the detector
if not isinstance(label, str):
raise ValueError(f"Expected a string label, but got {label} of type {type(label)}")
upper = label.upper()
if upper == Label.YES:
return DeprecatedLabel.PASS.value
if upper == Label.NO:
return DeprecatedLabel.FAIL.value

raise ValueError(f"Invalid label string '{label}'. Must be one of '{Label.YES.value}','{Label.NO.value}'.")
Loading