Skip to content

Commit

Permalink
[py-578][py-580] get properties endpoints (#747)
Browse files Browse the repository at this point in the history
* base annotation darwin

* fixes for annotations

* base str vs url

* tests for base annotation loading

* cleanup

* cleanup 2: electric boogaloo

* test bounding box auto-calculate

* typing

* cleanup

* property addition

* property metadata parsing

* cleanup validator

* test for properties base example

* linting

* Changes for list/get endpoint

* linting

* get_all_properties

* get properties and get by id

* linting

* base annotation darwin

* fixes for annotations

* base str vs url

* tests for base annotation loading

* cleanup

* cleanup 2: electric boogaloo

* test bounding box auto-calculate

* typing

* cleanup

* property metadata parsing

* cleanup validator

* test for properties base example

* Changes for list/get endpoint

* get_all_properties

* get properties and get by id

* linting

* linting

* QS helper and params checker on team_full_properties

* change for lower case True

* test change
  • Loading branch information
Nathanjp91 committed Dec 13, 2023
1 parent e12b601 commit 009ba15
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 3 deletions.
5 changes: 5 additions & 0 deletions darwin/future/core/properties/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from darwin.future.core.properties.get import (
get_property_by_id,
get_team_full_properties,
get_team_properties,
)
72 changes: 72 additions & 0 deletions darwin/future/core/properties/get.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from typing import List, Optional, Union
from uuid import UUID

from pydantic import parse_obj_as

from darwin.future.core.client import ClientCore
from darwin.future.core.types.common import QueryString
from darwin.future.data_objects.properties import FullProperty


def get_team_properties(
client: ClientCore,
team_slug: Optional[str] = None,
params: Optional[QueryString] = None,
) -> List[FullProperty]:
"""
Returns a List[FullProperty] object for the specified team slug.
Parameters:
client (ClientCore): The client to use for the request.
team_slug (Optional[str]): The slug of the team to get. If not specified, the
default team from the client's config will be used.
Returns:
List[FullProperty]: List of FullProperty objects for the specified team slug.
Raises:
HTTPError: If the response status code is not in the 200-299 range.
"""
if not team_slug:
team_slug = client.config.default_team
response = client.get(f"/v2/teams/{team_slug}/properties", query_string=params)
assert isinstance(response, dict)
return parse_obj_as(List[FullProperty], response.get("properties"))


def get_team_full_properties(
client: ClientCore,
team_slug: Optional[str] = None,
params: Optional[QueryString] = None,
) -> List[FullProperty]:
params = (
params + QueryString({"include_values": True})
if params and not params.get("include_values")
else QueryString({"include_values": True})
)
return get_team_properties(client, team_slug, params)


def get_property_by_id(
client: ClientCore, property_id: Union[str, UUID], team_slug: Optional[str] = None
) -> FullProperty:
"""
Returns a FullProperty object for the specified team slug.
Parameters:
client (ClientCore): The client to use for the request.
property_id (str | UUID): The ID of the property to get.
team_slug (Optional[str]): The slug of the team to get. If not specified, the
default team from the client's config will be used.
Returns:
FullProperty: FullProperty object from id
Raises:
HTTPError: If the response status code is not in the 200-299 range.
"""
if not team_slug:
team_slug = client.config.default_team
response = client.get(f"/v2/teams/{team_slug}/properties/{property_id}")
assert isinstance(response, dict)
return parse_obj_as(FullProperty, response)
7 changes: 5 additions & 2 deletions darwin/future/core/types/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,13 @@ def __str__(self) -> str:
for k, v in self.value.items():
if isinstance(v, list):
for x in v:
output += f"{k}={x}&"
output += f"{k}={x.lower()}&"
else:
output += f"{k}={v}&"
output += f"{k}={v.lower()}&"
return output[:-1] # remove trailing &

def __add__(self, other: QueryString) -> QueryString:
return QueryString({**self.value, **other.value})

def get(self, key: str, default: str = "") -> List[str] | str:
return self.value.get(key, default)
28 changes: 28 additions & 0 deletions darwin/future/tests/core/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,39 @@
from darwin.future.core.client import ClientCore, DarwinConfig
from darwin.future.data_objects.dataset import DatasetCore
from darwin.future.data_objects.item import ItemCore, ItemLayout, ItemSlot
from darwin.future.data_objects.properties import FullProperty, PropertyOption
from darwin.future.data_objects.team import TeamCore, TeamMemberCore
from darwin.future.data_objects.team_member_role import TeamMemberRole
from darwin.future.data_objects.workflow import WorkflowCore


@pytest.fixture
def base_property_option() -> PropertyOption:
return PropertyOption(
id="0",
position=0,
type="text",
value="test-value",
color="rgba(0,0,0,0)",
)


@pytest.fixture
def base_property_object(base_property_option: PropertyOption) -> FullProperty:
return FullProperty(
id="0",
name="test-property",
type="text",
description="test-description",
required=False,
slug="test-property",
team_id=0,
annotation_class_id=0,
property_values=[base_property_option],
options=[base_property_option],
)


@pytest.fixture
def base_config() -> DarwinConfig:
return DarwinConfig(
Expand Down
Empty file.
82 changes: 82 additions & 0 deletions darwin/future/tests/core/properties/test_get.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import responses
from responses.matchers import query_param_matcher

from darwin.future.core.client import ClientCore
from darwin.future.core.properties import (
get_property_by_id,
get_team_full_properties,
get_team_properties,
)
from darwin.future.core.types.common import QueryString
from darwin.future.data_objects.properties import FullProperty
from darwin.future.tests.core.fixtures import *


@responses.activate
def test_get_team_properties(
base_client: ClientCore, base_property_object: FullProperty
) -> None:
# Mocking the response using responses library
base_property_object.options = None
base_property_object.property_values = None
response_data = {"properties": [base_property_object.dict()]}
responses.add(
responses.GET,
f"{base_client.config.base_url}api/v2/teams/{base_client.config.default_team}/properties",
json=response_data,
status=200,
)

# Call the function being tested
properties = get_team_properties(base_client)

# Assertions
assert isinstance(properties, list)
assert all(isinstance(property, FullProperty) for property in properties)
assert properties[0] == base_property_object


@responses.activate
def test_get_team_full_properties(
base_client: ClientCore, base_property_object: FullProperty
) -> None:
# Mocking the response using responses library
response_data = {"properties": [base_property_object.dict()]}
responses.add(
responses.GET,
f"{base_client.config.base_url}api/v2/teams/{base_client.config.default_team}/properties",
match=[
query_param_matcher({"include_values": "true"}),
],
json=response_data,
status=200,
)
params = QueryString({"include_values": True})
# Call the function being tested
properties = get_team_full_properties(base_client, params=params)

# Assertions
assert isinstance(properties, list)
assert all(isinstance(property, FullProperty) for property in properties)
assert properties[0] == base_property_object


@responses.activate
def test_get_property_by_id(
base_client: ClientCore, base_property_object: FullProperty
) -> None:
# Mocking the response using responses library
property_id = "0"
responses.add(
responses.GET,
f"{base_client.config.base_url}api/v2/teams/{base_client.config.default_team}/properties/{property_id}",
json=base_property_object.dict(),
status=200,
)

# Call the function being tested
property = get_property_by_id(base_client, property_id)

# Assertions
assert isinstance(property, FullProperty)
assert property == base_property_object
4 changes: 3 additions & 1 deletion darwin/future/tests/data_objects/test_darwin.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def test_polygon_annotation(raw_json: dict):
PolygonAnnotation.parse_obj(polygon_annotation)


def test_polygon_bbx_vaidator(raw_json: dict):
def test_polygon_bbx_validator(raw_json: dict):
polygon_annotation = raw_json["annotations"][2]
without_bbx = polygon_annotation.copy()
del without_bbx["bounding_box"]
Expand All @@ -50,3 +50,5 @@ def test_polygon_bbx_vaidator(raw_json: dict):
assert without_bb_annotation.bounding_box is not None
assert with_bb_annotation.bounding_box is not None
assert without_bb_annotation == with_bb_annotation
bounds_annotation = raw_json["annotations"][0]
BoundingBoxAnnotation.parse_obj(bounds_annotation)

0 comments on commit 009ba15

Please sign in to comment.