Skip to content
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

[py-578][py-580] get properties endpoints #747

Merged
merged 43 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
25d1545
base annotation darwin
Nathanjp91 Dec 7, 2023
5aae6a6
fixes for annotations
Nathanjp91 Dec 7, 2023
5eda478
base str vs url
Nathanjp91 Dec 7, 2023
1b47f2f
tests for base annotation loading
Nathanjp91 Dec 7, 2023
7dce8ff
cleanup
Nathanjp91 Dec 7, 2023
a78fbb0
cleanup 2: electric boogaloo
Nathanjp91 Dec 7, 2023
fe50af7
test bounding box auto-calculate
Nathanjp91 Dec 7, 2023
1a23448
typing
Nathanjp91 Dec 7, 2023
bd9f035
cleanup
Nathanjp91 Dec 7, 2023
ffa0b28
property addition
Nathanjp91 Dec 8, 2023
153960a
property metadata parsing
Nathanjp91 Dec 8, 2023
3680490
cleanup validator
Nathanjp91 Dec 8, 2023
581d63e
test for properties base example
Nathanjp91 Dec 8, 2023
87074d5
linting
Nathanjp91 Dec 8, 2023
20def95
Merge branch 'py-573' into py-578
Nathanjp91 Dec 11, 2023
802c217
Changes for list/get endpoint
Nathanjp91 Dec 11, 2023
6decf44
linting
Nathanjp91 Dec 11, 2023
b6e6b50
Merge branch 'py-573' into py-578
Nathanjp91 Dec 11, 2023
b000467
get_all_properties
Nathanjp91 Dec 11, 2023
7965480
get properties and get by id
Nathanjp91 Dec 12, 2023
d15b8ff
Merge branch 'master' into py-578
Nathanjp91 Dec 12, 2023
c79d8aa
linting
Nathanjp91 Dec 12, 2023
7865e11
base annotation darwin
Nathanjp91 Dec 7, 2023
a9dcbb1
fixes for annotations
Nathanjp91 Dec 7, 2023
62e841f
base str vs url
Nathanjp91 Dec 7, 2023
11e193b
tests for base annotation loading
Nathanjp91 Dec 7, 2023
780b0e8
cleanup
Nathanjp91 Dec 7, 2023
48b26a8
cleanup 2: electric boogaloo
Nathanjp91 Dec 7, 2023
05b057a
test bounding box auto-calculate
Nathanjp91 Dec 7, 2023
f5a795a
typing
Nathanjp91 Dec 7, 2023
7aae491
cleanup
Nathanjp91 Dec 7, 2023
8a32881
property metadata parsing
Nathanjp91 Dec 8, 2023
088e37c
cleanup validator
Nathanjp91 Dec 8, 2023
653697a
test for properties base example
Nathanjp91 Dec 8, 2023
f1670d1
Changes for list/get endpoint
Nathanjp91 Dec 11, 2023
f55a12c
get_all_properties
Nathanjp91 Dec 11, 2023
c5fd349
get properties and get by id
Nathanjp91 Dec 12, 2023
91ac90b
linting
Nathanjp91 Dec 12, 2023
92cd2b3
linting
Nathanjp91 Dec 12, 2023
e11593b
Merge branch 'py-578' of github.com:v7labs/darwin-py into py-578
Nathanjp91 Dec 12, 2023
69d8ebf
QS helper and params checker on team_full_properties
Nathanjp91 Dec 12, 2023
4fcfbdd
change for lower case True
Nathanjp91 Dec 13, 2023
e2a2e42
test change
Nathanjp91 Dec 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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})
saurbhc marked this conversation as resolved.
Show resolved Hide resolved
)
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)
3 changes: 3 additions & 0 deletions darwin/future/core/types/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,6 @@ def __str__(self) -> str:

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)