diff --git a/generated/.openapi-generator/FILES b/generated/.openapi-generator/FILES index 928613a0..c90ff404 100644 --- a/generated/.openapi-generator/FILES +++ b/generated/.openapi-generator/FILES @@ -18,6 +18,7 @@ docs/BoundingBoxLabelEnum.md docs/BoundingBoxModeConfiguration.md docs/BoundingBoxResult.md docs/ChannelEnum.md +docs/CustomerGroup.md docs/Condition.md docs/ConditionRequest.md docs/CountModeConfiguration.md @@ -40,7 +41,6 @@ docs/ImageQueryTypeEnum.md docs/InlineResponse200.md docs/InlineResponse2001.md docs/InlineResponse2001EvaluationResults.md -docs/InlineResponse2002.md docs/InlineResponse200Summary.md docs/InlineResponse200SummaryClassCounts.md docs/Label.md @@ -48,6 +48,7 @@ docs/LabelValue.md docs/LabelValueRequest.md docs/LabelsApi.md docs/MLPipeline.md +docs/Me.md docs/ModeEnum.md docs/MonthToDateAccountInfoApi.md docs/MultiClassModeConfiguration.md @@ -129,6 +130,7 @@ groundlight_openapi_client/model/condition.py groundlight_openapi_client/model/condition_request.py groundlight_openapi_client/model/count_mode_configuration.py groundlight_openapi_client/model/counting_result.py +groundlight_openapi_client/model/customer_group.py groundlight_openapi_client/model/detector.py groundlight_openapi_client/model/detector_creation_input_request.py groundlight_openapi_client/model/detector_group.py @@ -142,12 +144,12 @@ groundlight_openapi_client/model/image_query_type_enum.py groundlight_openapi_client/model/inline_response200.py groundlight_openapi_client/model/inline_response2001.py groundlight_openapi_client/model/inline_response2001_evaluation_results.py -groundlight_openapi_client/model/inline_response2002.py groundlight_openapi_client/model/inline_response200_summary.py groundlight_openapi_client/model/inline_response200_summary_class_counts.py groundlight_openapi_client/model/label.py groundlight_openapi_client/model/label_value.py groundlight_openapi_client/model/label_value_request.py +groundlight_openapi_client/model/me.py groundlight_openapi_client/model/ml_pipeline.py groundlight_openapi_client/model/mode_enum.py groundlight_openapi_client/model/multi_class_mode_configuration.py diff --git a/generated/README.md b/generated/README.md index fb70bd29..c176162e 100644 --- a/generated/README.md +++ b/generated/README.md @@ -188,7 +188,8 @@ Class | Method | HTTP request | Description - [InlineResponse200](docs/InlineResponse200.md) - [InlineResponse2001](docs/InlineResponse2001.md) - [InlineResponse2001EvaluationResults](docs/InlineResponse2001EvaluationResults.md) - - [InlineResponse2002](docs/InlineResponse2002.md) + - [CustomerGroup](docs/CustomerGroup.md) + - [Me](docs/Me.md) - [InlineResponse200Summary](docs/InlineResponse200Summary.md) - [InlineResponse200SummaryClassCounts](docs/InlineResponse200SummaryClassCounts.md) - [Label](docs/Label.md) diff --git a/generated/docs/InlineResponse2002.md b/generated/docs/CustomerGroup.md similarity index 69% rename from generated/docs/InlineResponse2002.md rename to generated/docs/CustomerGroup.md index 59b1a320..ab7edeae 100644 --- a/generated/docs/InlineResponse2002.md +++ b/generated/docs/CustomerGroup.md @@ -1,10 +1,12 @@ -# InlineResponse2002 +# CustomerGroup +A Groundlight customer group (tenant) the authenticated user belongs to. ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**username** | **str** | The user's username | [optional] +**id** | **int** | Numeric id of the customer group. | +**name** | **str** | Name of the customer group. | **any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/generated/docs/Me.md b/generated/docs/Me.md new file mode 100644 index 00000000..c7dd86ba --- /dev/null +++ b/generated/docs/Me.md @@ -0,0 +1,16 @@ +# Me + +Authenticated user identity from GET /v1/me (id, email, username, groups). + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **int** | Numeric id of the authenticated user. | +**email** | **str** | Email address of the authenticated user. | +**username** | **str** | Username of the authenticated user. | +**groups** | [**[CustomerGroup]**](CustomerGroup.md) | Customer groups the authenticated user belongs to. | +**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/generated/docs/UserApi.md b/generated/docs/UserApi.md index b10f06bc..27825aa5 100644 --- a/generated/docs/UserApi.md +++ b/generated/docs/UserApi.md @@ -8,11 +8,11 @@ Method | HTTP request | Description # **who_am_i** -> InlineResponse2002 who_am_i() +> Me who_am_i() -Retrieve the current user. +Retrieve the authenticated user's id, email, username, and customer groups. ### Example @@ -22,7 +22,7 @@ Retrieve the current user. import time import groundlight_openapi_client from groundlight_openapi_client.api import user_api -from groundlight_openapi_client.model.inline_response2002 import InlineResponse2002 +from groundlight_openapi_client.model.me import Me from pprint import pprint # Defining the host is optional and defaults to https://api.groundlight.ai/device-api # See configuration.py for a list of all supported configuration parameters. @@ -60,7 +60,7 @@ This endpoint does not need any parameter. ### Return type -[**InlineResponse2002**](InlineResponse2002.md) +[**Me**](Me.md) ### Authorization diff --git a/generated/groundlight_openapi_client/api/user_api.py b/generated/groundlight_openapi_client/api/user_api.py index a14200f2..ec1e6c9c 100644 --- a/generated/groundlight_openapi_client/api/user_api.py +++ b/generated/groundlight_openapi_client/api/user_api.py @@ -21,7 +21,7 @@ none_type, validate_and_convert_types, ) -from groundlight_openapi_client.model.inline_response2002 import InlineResponse2002 +from groundlight_openapi_client.model.me import Me class UserApi(object): @@ -37,7 +37,7 @@ def __init__(self, api_client=None): self.api_client = api_client self.who_am_i_endpoint = _Endpoint( settings={ - "response_type": (InlineResponse2002,), + "response_type": (Me,), "auth": ["ApiToken"], "endpoint_path": "/v1/me", "operation_id": "who_am_i", @@ -63,7 +63,7 @@ def __init__(self, api_client=None): def who_am_i(self, **kwargs): """who_am_i # noqa: E501 - Retrieve the current user. # noqa: E501 + Retrieve the authenticated user's id, email, username, and customer groups. # noqa: E501 This method makes a synchronous HTTP request by default. To make an asynchronous HTTP request, please pass async_req=True @@ -100,7 +100,7 @@ def who_am_i(self, **kwargs): async_req (bool): execute request asynchronously Returns: - InlineResponse2002 + Me If the method is called asynchronously, returns the request thread. """ diff --git a/generated/groundlight_openapi_client/model/inline_response2002.py b/generated/groundlight_openapi_client/model/customer_group.py similarity index 77% rename from generated/groundlight_openapi_client/model/inline_response2002.py rename to generated/groundlight_openapi_client/model/customer_group.py index 1fbfd51d..6c101b4f 100644 --- a/generated/groundlight_openapi_client/model/inline_response2002.py +++ b/generated/groundlight_openapi_client/model/customer_group.py @@ -8,6 +8,7 @@ Generated by: https://openapi-generator.tech """ + import re # noqa: F401 import sys # noqa: F401 @@ -24,12 +25,13 @@ file_type, none_type, validate_get_composed_info, - OpenApiModel, + OpenApiModel ) from groundlight_openapi_client.exceptions import ApiAttributeError -class InlineResponse2002(ModelNormal): + +class CustomerGroup(ModelNormal): """NOTE: This class is auto generated by OpenAPI Generator. Ref: https://openapi-generator.tech @@ -53,9 +55,11 @@ class InlineResponse2002(ModelNormal): as additional properties values. """ - allowed_values = {} + allowed_values = { + } - validations = {} + validations = { + } @cached_property def additional_properties_type(): @@ -63,17 +67,7 @@ def additional_properties_type(): This must be a method because a model may have properties that are of type self, this must run after the class is loaded """ - 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 @@ -88,25 +82,33 @@ def openapi_types(): and the value is attribute type. """ return { - "username": (str,), # noqa: E501 + 'id': (int,), # noqa: E501 + 'name': (str,), # noqa: E501 } @cached_property def discriminator(): return None + attribute_map = { - "username": "username", # noqa: E501 + 'id': 'id', # noqa: E501 + 'name': 'name', # noqa: E501 } - read_only_vars = {} + read_only_vars = { + } _composed_schemas = {} @classmethod @convert_js_args_to_python_args - def _from_openapi_data(cls, *args, **kwargs): # noqa: E501 - """InlineResponse2002 - a model defined in OpenAPI + def _from_openapi_data(cls, id, name, *args, **kwargs): # noqa: E501 + """CustomerGroup - a model defined in OpenAPI + + Args: + id (int): Numeric id of the customer group. + name (str): Name of the customer group. Keyword Args: _check_type (bool): if True, values for parameters in openapi_types @@ -139,21 +141,19 @@ def _from_openapi_data(cls, *args, **kwargs): # noqa: E501 Animal class but this time we won't travel through its discriminator because we passed in _visited_composed_classes = (Animal,) - username (str): The user's username. [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__, ), @@ -168,30 +168,34 @@ def _from_openapi_data(cls, *args, **kwargs): # noqa: E501 self._configuration = _configuration self._visited_composed_classes = _visited_composed_classes + (self.__class__,) + self.id = id + self.name = name 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 - def __init__(self, *args, **kwargs): # noqa: E501 - """InlineResponse2002 - a model defined in OpenAPI + def __init__(self, id, name, *args, **kwargs): # noqa: E501 + """CustomerGroup - a model defined in OpenAPI + + Args: + id (int): Numeric id of the customer group. + name (str): Name of the customer group. Keyword Args: _check_type (bool): if True, values for parameters in openapi_types @@ -224,19 +228,17 @@ def __init__(self, *args, **kwargs): # noqa: E501 Animal class but this time we won't travel through its discriminator because we passed in _visited_composed_classes = (Animal,) - username (str): The user's username. [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__, ), @@ -251,18 +253,16 @@ def __init__(self, *args, **kwargs): # noqa: E501 self._configuration = _configuration self._visited_composed_classes = _visited_composed_classes + (self.__class__,) + self.id = id + self.name = name 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 " - "class with read only attributes." - ) + raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate " + f"class with read only attributes.") diff --git a/generated/groundlight_openapi_client/model/me.py b/generated/groundlight_openapi_client/model/me.py new file mode 100644 index 00000000..c8c6cde8 --- /dev/null +++ b/generated/groundlight_openapi_client/model/me.py @@ -0,0 +1,286 @@ +""" + Groundlight API + + Groundlight makes it simple to understand images. You can easily create computer vision detectors just by describing what you want to know using natural language. # noqa: E501 + + The version of the OpenAPI document: 0.18.2 + Contact: support@groundlight.ai + Generated by: https://openapi-generator.tech +""" + + +import re # noqa: F401 +import sys # noqa: F401 + +from groundlight_openapi_client.model_utils import ( # noqa: F401 + ApiTypeError, + ModelComposed, + ModelNormal, + ModelSimple, + cached_property, + change_keys_js_to_python, + convert_js_args_to_python_args, + date, + datetime, + file_type, + none_type, + validate_get_composed_info, + OpenApiModel +) +from groundlight_openapi_client.exceptions import ApiAttributeError + + +def lazy_import(): + from groundlight_openapi_client.model.customer_group import CustomerGroup + globals()['CustomerGroup'] = CustomerGroup + + +class Me(ModelNormal): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + + Attributes: + allowed_values (dict): The key is the tuple path to the attribute + and the for var_name this is (var_name,). The value is a dict + with a capitalized key describing the allowed value and an allowed + value. These dicts store the allowed enum values. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + discriminator_value_class_map (dict): A dict to go from the discriminator + variable value to the discriminator class name. + validations (dict): The key is the tuple path to the attribute + and the for var_name this is (var_name,). The value is a dict + that stores validations for max_length, min_length, max_items, + min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum, + inclusive_minimum, and regex. + additional_properties_type (tuple): A tuple of classes accepted + as additional properties values. + """ + + allowed_values = { + } + + validations = { + } + + @cached_property + def additional_properties_type(): + """ + This must be a method because a model may have properties that are + 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 + + _nullable = False + + @cached_property + def openapi_types(): + """ + This must be a method because a model may have properties that are + of type self, this must run after the class is loaded + + Returns + openapi_types (dict): The key is attribute name + and the value is attribute type. + """ + lazy_import() + return { + 'id': (int,), # noqa: E501 + 'email': (str,), # noqa: E501 + 'username': (str,), # noqa: E501 + 'groups': ([CustomerGroup],), # noqa: E501 + } + + @cached_property + def discriminator(): + return None + + + attribute_map = { + 'id': 'id', # noqa: E501 + 'email': 'email', # noqa: E501 + 'username': 'username', # noqa: E501 + 'groups': 'groups', # noqa: E501 + } + + read_only_vars = { + } + + _composed_schemas = {} + + @classmethod + @convert_js_args_to_python_args + def _from_openapi_data(cls, id, email, username, groups, *args, **kwargs): # noqa: E501 + """Me - a model defined in OpenAPI + + Args: + id (int): Numeric id of the authenticated user. + email (str): Email address of the authenticated user. + username (str): Username of the authenticated user. + groups ([CustomerGroup]): Customer groups the authenticated user belongs to. + + Keyword Args: + _check_type (bool): if True, values for parameters in openapi_types + will be type checked and a TypeError will be + raised if the wrong type is input. + Defaults to True + _path_to_item (tuple/list): This is a list of keys or values to + drill down to the model in received_data + when deserializing a response + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) + _configuration (Configuration): the instance to use when + deserializing a file_type parameter. + If passed, type conversion is attempted + If omitted no type conversion is done. + _visited_composed_classes (tuple): This stores a tuple of + classes that we have traveled through so that + if we see that class again we will not use its + discriminator again. + When traveling through a discriminator, the + composed schema that is + is traveled through is added to this set. + For example if Animal has a discriminator + petType and we pass in "Dog", and the class Dog + allOf includes Animal, we move through Animal + once using the discriminator, and pick Dog. + Then in Dog, we will make an instance of the + Animal class but this time we won't travel + through its discriminator because we passed in + _visited_composed_classes = (Animal,) + """ + + _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." % ( + args, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + self._data_store = {} + self._check_type = _check_type + self._spec_property_naming = _spec_property_naming + self._path_to_item = _path_to_item + self._configuration = _configuration + self._visited_composed_classes = _visited_composed_classes + (self.__class__,) + + self.id = id + self.email = email + self.username = username + self.groups = groups + 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: + # 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', + ]) + + @convert_js_args_to_python_args + def __init__(self, id, email, username, groups, *args, **kwargs): # noqa: E501 + """Me - a model defined in OpenAPI + + Args: + id (int): Numeric id of the authenticated user. + email (str): Email address of the authenticated user. + username (str): Username of the authenticated user. + groups ([CustomerGroup]): Customer groups the authenticated user belongs to. + + Keyword Args: + _check_type (bool): if True, values for parameters in openapi_types + will be type checked and a TypeError will be + raised if the wrong type is input. + Defaults to True + _path_to_item (tuple/list): This is a list of keys or values to + drill down to the model in received_data + when deserializing a response + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) + _configuration (Configuration): the instance to use when + deserializing a file_type parameter. + If passed, type conversion is attempted + If omitted no type conversion is done. + _visited_composed_classes (tuple): This stores a tuple of + classes that we have traveled through so that + if we see that class again we will not use its + discriminator again. + When traveling through a discriminator, the + composed schema that is + is traveled through is added to this set. + For example if Animal has a discriminator + petType and we pass in "Dog", and the class Dog + allOf includes Animal, we move through Animal + once using the discriminator, and pick Dog. + Then in Dog, we will make an instance of the + Animal class but this time we won't travel + through its discriminator because we passed in + _visited_composed_classes = (Animal,) + """ + + _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." % ( + args, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + self._data_store = {} + self._check_type = _check_type + self._spec_property_naming = _spec_property_naming + self._path_to_item = _path_to_item + self._configuration = _configuration + self._visited_composed_classes = _visited_composed_classes + (self.__class__,) + + self.id = id + self.email = email + self.username = username + self.groups = groups + 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: + # 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.") diff --git a/generated/groundlight_openapi_client/models/__init__.py b/generated/groundlight_openapi_client/models/__init__.py index fcc8fd76..60d2d38f 100644 --- a/generated/groundlight_openapi_client/models/__init__.py +++ b/generated/groundlight_openapi_client/models/__init__.py @@ -29,6 +29,7 @@ from groundlight_openapi_client.model.condition_request import ConditionRequest from groundlight_openapi_client.model.count_mode_configuration import CountModeConfiguration from groundlight_openapi_client.model.counting_result import CountingResult +from groundlight_openapi_client.model.customer_group import CustomerGroup from groundlight_openapi_client.model.detector import Detector from groundlight_openapi_client.model.detector_creation_input_request import DetectorCreationInputRequest from groundlight_openapi_client.model.detector_group import DetectorGroup @@ -42,12 +43,12 @@ from groundlight_openapi_client.model.inline_response200 import InlineResponse200 from groundlight_openapi_client.model.inline_response2001 import InlineResponse2001 from groundlight_openapi_client.model.inline_response2001_evaluation_results import InlineResponse2001EvaluationResults -from groundlight_openapi_client.model.inline_response2002 import InlineResponse2002 from groundlight_openapi_client.model.inline_response200_summary import InlineResponse200Summary from groundlight_openapi_client.model.inline_response200_summary_class_counts import InlineResponse200SummaryClassCounts from groundlight_openapi_client.model.label import Label from groundlight_openapi_client.model.label_value import LabelValue from groundlight_openapi_client.model.label_value_request import LabelValueRequest +from groundlight_openapi_client.model.me import Me from groundlight_openapi_client.model.ml_pipeline import MLPipeline from groundlight_openapi_client.model.mode_enum import ModeEnum from groundlight_openapi_client.model.multi_class_mode_configuration import MultiClassModeConfiguration diff --git a/generated/model.py b/generated/model.py index 4659a06e..3ed2bc68 100644 --- a/generated/model.py +++ b/generated/model.py @@ -132,6 +132,26 @@ class DetectorGroupRequest(BaseModel): name: constr(min_length=1, max_length=100) +class CustomerGroup(BaseModel): + """ + A Groundlight customer group (tenant) the authenticated user belongs to. + """ + + id: int = Field(..., description="Numeric id of the customer group.") + name: str = Field(..., description="Name of the customer group.") + + +class Me(BaseModel): + """ + Authenticated user identity from GET /v1/me (id, email, username, groups). + """ + + id: int = Field(..., description="Numeric id of the authenticated user.") + email: str = Field(..., description="Email address of the authenticated user.") + username: str = Field(..., description="Username of the authenticated user.") + groups: List[CustomerGroup] = Field(..., description="Customer groups the authenticated user belongs to.") + + class DetectorModeEnum(str, Enum): """ * `BINARY` - BINARY diff --git a/generated/test/test_inline_response2002.py b/generated/test/test_customer_group.py similarity index 64% rename from generated/test/test_inline_response2002.py rename to generated/test/test_customer_group.py index 84922f0f..6dbbb664 100644 --- a/generated/test/test_inline_response2002.py +++ b/generated/test/test_customer_group.py @@ -8,15 +8,16 @@ Generated by: https://openapi-generator.tech """ + import sys import unittest import groundlight_openapi_client -from groundlight_openapi_client.model.inline_response2002 import InlineResponse2002 +from groundlight_openapi_client.model.customer_group import CustomerGroup -class TestInlineResponse2002(unittest.TestCase): - """InlineResponse2002 unit test stubs""" +class TestCustomerGroup(unittest.TestCase): + """CustomerGroup unit test stubs""" def setUp(self): pass @@ -24,12 +25,12 @@ def setUp(self): def tearDown(self): pass - def testInlineResponse2002(self): - """Test InlineResponse2002""" + def testCustomerGroup(self): + """Test CustomerGroup""" # FIXME: construct object with mandatory attributes with example values - # model = InlineResponse2002() # noqa: E501 + # model = CustomerGroup() # noqa: E501 pass -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/generated/test/test_me.py b/generated/test/test_me.py new file mode 100644 index 00000000..0248197d --- /dev/null +++ b/generated/test/test_me.py @@ -0,0 +1,38 @@ +""" + Groundlight API + + Groundlight makes it simple to understand images. You can easily create computer vision detectors just by describing what you want to know using natural language. # noqa: E501 + + The version of the OpenAPI document: 0.18.2 + Contact: support@groundlight.ai + Generated by: https://openapi-generator.tech +""" + + +import sys +import unittest + +import groundlight_openapi_client +from groundlight_openapi_client.model.customer_group import CustomerGroup +globals()['CustomerGroup'] = CustomerGroup +from groundlight_openapi_client.model.me import Me + + +class TestMe(unittest.TestCase): + """Me unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testMe(self): + """Test Me""" + # FIXME: construct object with mandatory attributes with example values + # model = Me() # noqa: E501 + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/spec/public-api.yaml b/spec/public-api.yaml index 9e6a17a2..6b4bc947 100644 --- a/spec/public-api.yaml +++ b/spec/public-api.yaml @@ -865,7 +865,8 @@ paths: /v1/me: get: operationId: Who am I - description: Retrieve the current user. + description: Retrieve the authenticated user's id, email, username, and customer + groups. tags: - user security: @@ -875,11 +876,7 @@ paths: content: application/json: schema: - type: object - properties: - username: - type: string - description: The user's username + $ref: '#/components/schemas/Me' description: '' /v1/month-to-date-account-info: get: @@ -1346,6 +1343,20 @@ components: required: - parameters - verb + CustomerGroup: + type: object + description: A Groundlight customer group (tenant) the authenticated user belongs + to. + properties: + id: + type: integer + description: Numeric id of the customer group. + name: + type: string + description: Name of the customer group. + required: + - id + - name Detector: type: object description: |- @@ -1828,6 +1839,30 @@ components: - training_in_progress - type x-internal: true + Me: + type: object + description: Authenticated user identity from GET /v1/me (id, email, username, + groups). + properties: + id: + type: integer + description: Numeric id of the authenticated user. + email: + type: string + description: Email address of the authenticated user. + username: + type: string + description: Username of the authenticated user. + groups: + type: array + items: + $ref: '#/components/schemas/CustomerGroup' + description: Customer groups the authenticated user belongs to. + required: + - email + - groups + - id + - username ModeEnum: type: string enum: diff --git a/src/groundlight/cli.py b/src/groundlight/cli.py index 698ff655..f3fec131 100644 --- a/src/groundlight/cli.py +++ b/src/groundlight/cli.py @@ -190,6 +190,7 @@ def wrapper(*args, **kwargs): _COMMAND_GROUPS: dict[str, str] = { # Account "whoami": "Account", + "me": "Account", "get_month_to_date_usage": "Account", # Detectors "get_detector": "Detectors", diff --git a/src/groundlight/client.py b/src/groundlight/client.py index c988c8f1..33a3d0ce 100644 --- a/src/groundlight/client.py +++ b/src/groundlight/client.py @@ -33,6 +33,7 @@ Detector, DetectorGroup, ImageQuery, + Me, ModeEnum, PaginatedDetectorList, PaginatedImageQueryList, @@ -280,6 +281,23 @@ def _fixup_image_query(iq: ImageQuery) -> ImageQuery: iq.result.label = convert_internal_label_to_display(iq, iq.result.label) return iq + def me(self) -> Me: + """ + Return user identity information for the current API token. + + **Example usage**:: + + gl = Groundlight() + me = gl.me() + print(f"Authenticated as {me.email} in {[g.name for g in me.groups]}") + + :return: Me object for the authenticated user + :raises ApiTokenError: If the API token is invalid + :raises GroundlightClientError: If there are connectivity issues with the Groundlight service + """ + obj = self.user_api.who_am_i(_request_timeout=DEFAULT_REQUEST_TIMEOUT) + return Me.model_validate(obj.to_dict()) + def whoami(self) -> str: """ Return the username (email address) associated with the current API token. @@ -297,8 +315,7 @@ def whoami(self) -> str: :raises ApiTokenError: If the API token is invalid :raises GroundlightClientError: If there are connectivity issues with the Groundlight service """ - obj = self.user_api.who_am_i(_request_timeout=DEFAULT_REQUEST_TIMEOUT) - return obj["email"] + return self.me().email def _user_is_privileged(self) -> bool: """ diff --git a/test/unit/test_user.py b/test/unit/test_user.py index 927da25b..d9d39631 100644 --- a/test/unit/test_user.py +++ b/test/unit/test_user.py @@ -1,7 +1,22 @@ from groundlight import Groundlight +from model import CustomerGroup, Me def test_whoami(gl: Groundlight): user = gl.whoami() assert user is not None assert isinstance(user, str) + + +def test_me(gl: Groundlight): + """me() returns structured identity including customer groups from /v1/me.""" + me = gl.me() + assert isinstance(me, Me) + assert isinstance(me.id, int) + assert me.email + assert me.username + assert isinstance(me.groups, list) + assert len(me.groups) >= 1 + assert all(isinstance(group, CustomerGroup) for group in me.groups) + assert all(group.id and group.name for group in me.groups) + assert gl.whoami() == me.email