Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "bloomy-python"
version = "0.21.2"
version = "0.22.0"
description = "Python SDK for Bloom Growth API"
readme = "README.md"
authors = [{ name = "Franccesco Orozco", email = "franccesco@codingdose.info" }]
Expand Down
5 changes: 5 additions & 0 deletions src/bloomy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ def _parse_optional_float(v: Any) -> float | None:
# Reusable annotated types for optional fields that may come as empty strings
OptionalDatetime = Annotated[datetime | None, BeforeValidator(_parse_optional_datetime)]
OptionalFloat = Annotated[float | None, BeforeValidator(_parse_optional_float)]
# Coerces a nullable value (e.g. a datetime or None) into a bool (present = True)
IsPresent = Annotated[bool, BeforeValidator(lambda v: v is not None and v != "")]


class GoalStatus(StrEnum):
Expand Down Expand Up @@ -157,6 +159,7 @@ class Todo(BloomyBaseModel):
meeting_id: int | None = Field(alias="OriginId", default=None)
meeting_name: str | None = Field(alias="Origin", default=None)
complete: bool = Field(alias="Complete", default=False)
archived: IsPresent = Field(alias="CloseTime", default=False)


class Issue(BloomyBaseModel):
Expand Down Expand Up @@ -301,6 +304,7 @@ class IssueDetails(BloomyBaseModel):
notes_url: str
created_at: str
completed_at: str | None = None
archived: bool = False
meeting_id: int
meeting_title: str
user_id: int
Expand All @@ -314,6 +318,7 @@ class IssueListItem(BloomyBaseModel):
title: str
notes_url: str
created_at: str
archived: bool = False
meeting_id: int
meeting_title: str | None

Expand Down
1 change: 1 addition & 0 deletions src/bloomy/operations/async_/todos.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ async def create(
"DetailsUrl": data.get("DetailsUrl"),
"DueDate": data.get("DueDate"),
"CompleteTime": None,
"CloseTime": None,
"CreateTime": data.get("CreateTime", datetime.now(UTC).isoformat()),
"OriginId": meeting_id,
"Origin": None,
Expand Down
2 changes: 2 additions & 0 deletions src/bloomy/operations/mixins/issues_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def _transform_issue_details(self, data: dict[str, Any]) -> IssueDetails:
notes_url=data["DetailsUrl"],
created_at=data["CreateTime"],
completed_at=data["CloseTime"],
archived=data["Archived"],
meeting_id=data["OriginId"],
meeting_title=data["Origin"],
user_id=data["Owner"]["Id"],
Expand All @@ -57,6 +58,7 @@ def _transform_issue_list(
title=issue["Name"],
notes_url=issue["DetailsUrl"],
created_at=issue["CreateTime"],
archived=issue["Archived"],
meeting_id=issue["OriginId"],
meeting_title=issue["Origin"],
)
Expand Down
1 change: 1 addition & 0 deletions src/bloomy/operations/todos.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ def create(
"DetailsUrl": data.get("DetailsUrl"),
"DueDate": data.get("DueDate"),
"CompleteTime": None,
"CloseTime": None,
"CreateTime": data.get("CreateTime", datetime.now(UTC).isoformat()),
"OriginId": meeting_id,
"Origin": None,
Expand Down
2 changes: 2 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def sample_todo_data() -> dict[str, Any]:
"Complete": False,
"CreateTime": "2024-01-01T10:00:00Z",
"CompleteTime": None,
"CloseTime": None,
"Owner": {"Id": 123, "Name": "John Doe"},
}

Expand Down Expand Up @@ -170,6 +171,7 @@ def sample_issue_data() -> dict[str, Any]:
"CreateTime": "2024-06-01T10:00:00Z",
"CloseTime": None,
"Complete": False,
"Archived": False,
"Owner": {"Id": 123, "Name": "John Doe"},
"Origin": "Infrastructure Meeting",
"OriginId": 456,
Expand Down
3 changes: 3 additions & 0 deletions tests/test_adversarial_issues_headlines.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ def test_owner_is_none_raises_type_error(self) -> None:
"DetailsUrl": "http://example.com",
"CreateTime": "2024-01-01",
"CloseTime": None,
"Archived": False,
"OriginId": 10,
"Origin": "Meeting",
"Owner": None,
Expand All @@ -405,6 +406,7 @@ def test_close_time_none_succeeds(self) -> None:
"DetailsUrl": "http://example.com",
"CreateTime": "2024-01-01",
"CloseTime": None,
"Archived": False,
"OriginId": 10,
"Origin": "Meeting",
"Owner": {"Id": 1, "Name": "John"},
Expand All @@ -421,6 +423,7 @@ def test_close_time_empty_string(self) -> None:
"DetailsUrl": "http://example.com",
"CreateTime": "2024-01-01",
"CloseTime": "",
"Archived": False,
"OriginId": 10,
"Origin": "Meeting",
"Owner": {"Id": 1, "Name": "John"},
Expand Down
2 changes: 2 additions & 0 deletions tests/test_issues.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def test_list_user_issues(self, mock_http_client: Mock, mock_user_id: Mock) -> N
"Origin": "Infrastructure Meeting",
"OriginId": 456,
"DetailsUrl": "https://example.com/issue/401",
"Archived": False,
}
]
mock_http_client.get.return_value = mock_response
Expand Down Expand Up @@ -68,6 +69,7 @@ def test_list_meeting_issues(self, mock_http_client: Mock) -> None:
"Origin": "Infrastructure Meeting",
"OriginId": 456,
"DetailsUrl": "https://example.com/issue/401",
"Archived": False,
}
]
mock_http_client.get.return_value = mock_response
Expand Down
Loading