Skip to content

Commit

Permalink
feat: add checklist support
Browse files Browse the repository at this point in the history
  • Loading branch information
danfimov committed Sep 28, 2023
1 parent c6dd719 commit 7d9bfb4
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 23 deletions.
4 changes: 2 additions & 2 deletions ya_tracker_client/domain/client/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from abc import ABC, abstractmethod
from http import HTTPStatus
from json import dumps
from logging import getLogger
from typing import Any

Expand All @@ -14,6 +13,7 @@
ClientObjectNotFoundError,
ClientSufficientRightsError,
)
from ya_tracker_client.utils import serialize_entity


logger = getLogger(__name__)
Expand Down Expand Up @@ -60,7 +60,7 @@ async def request(
uri = f"{self._base_url}/{self._api_version}{uri}"

bytes_payload = BytesPayload(
value=bytes(dumps(payload), encoding="utf-8"),
value=bytes(serialize_entity(payload), encoding="utf-8"),
content_type="application/json",
)

Expand Down
22 changes: 15 additions & 7 deletions ya_tracker_client/domain/entities/checklist.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@

from ya_tracker_client.domain.entities.base import AbstractEntity
from ya_tracker_client.domain.entities.deadline import Deadline
from ya_tracker_client.domain.entities.user import UserShort


class ChecklistCreate(AbstractEntity):
Expand All @@ -9,12 +11,18 @@ class ChecklistCreate(AbstractEntity):
deadline: Deadline | None = None


class Checklist(AbstractEntity):
...
class ChecklistItem(AbstractEntity):
id: str
text: str
text_html: str
checked: bool
checklist_item_type: str
deadline: Deadline | None = None
assignee: UserShort | None = None


class IssueWithoutChecklist(AbstractEntity):
url: str
id: str
key: str
version: int
class ChecklistItemEdit(AbstractEntity):
text: str
checked: bool | None = None
assignee: str | None = None
deadline: Deadline | None = None
3 changes: 2 additions & 1 deletion ya_tracker_client/domain/entities/deadline.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@

class Deadline(AbstractEntity):
date: datetime
deadline_type: str = "deadline"
deadline_type: str = "date"
is_exceeded: bool | None = None
35 changes: 35 additions & 0 deletions ya_tracker_client/domain/entities/issue.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from datetime import datetime

from pydantic import Field

from ya_tracker_client.domain.entities.base import AbstractEntity
from ya_tracker_client.domain.entities.checklist import ChecklistItem
from ya_tracker_client.domain.entities.issue_status import IssueStatus
from ya_tracker_client.domain.entities.issue_type import IssueType
from ya_tracker_client.domain.entities.priority import Priority
from ya_tracker_client.domain.entities.queue import QueueIdentifier, QueueShort
Expand Down Expand Up @@ -68,3 +72,34 @@ class IssueEdit(AbstractEntity):
type: IssueType | None = None
priority: Priority | None = None
followers: list[UserShort | str] | None = None


class IssueWithChecklist(AbstractEntity):
url: str
id: str
key: str
version: int

summary: str
description: str | None = None
type: IssueType
priority: Priority
followers: list[UserShort] | None = None
queue: QueueShort
favorite: bool
assignee: UserShort | None = None

last_comment_updated_at: datetime | None = None
pending_reply_from: UserShort | None = None
created_at: datetime
updated_at: datetime
created_by: UserShort
updated_by: UserShort | None = None
votes: int
status: IssueStatus
previous_status: IssueStatus | None = None
status_start_time: datetime
previous_status_last_assignee: UserShort | None = None
deadline: datetime | None = None

checklist_items: list[ChecklistItem] = Field(default_factory=list)
70 changes: 62 additions & 8 deletions ya_tracker_client/domain/repositories/checklist.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
from json import loads
from logging import getLogger

from ya_tracker_client.domain.entities.checklist import Checklist, ChecklistCreate
from ya_tracker_client.domain.entities.checklist import ChecklistCreate, ChecklistItem, ChecklistItemEdit
from ya_tracker_client.domain.entities.deadline import Deadline
from ya_tracker_client.domain.entities.issue import IssueWithChecklist
from ya_tracker_client.domain.repositories.base import EntityRepository


logger = getLogger(__name__)


class ChecklistRepository(EntityRepository):
async def create_checklist_item(
self,
Expand All @@ -17,8 +14,10 @@ async def create_checklist_item(
checked: bool | None = None,
assignee: str | None = None,
deadline: Deadline | None = None,
) -> Checklist:
) -> IssueWithChecklist:
"""
Use this request to create a checklist and add new items to it.
YC docs: https://cloud.yandex.com/en/docs/tracker/concepts/issues/add-checklist-item
"""
raw_response = await self._client.request(
Expand All @@ -31,5 +30,60 @@ async def create_checklist_item(
deadline=deadline,
).model_dump(exclude_none=True, by_alias=True),
)
print(raw_response)
return Checklist(**loads(raw_response))
return IssueWithChecklist(**loads(raw_response))

async def get_checklist_items(self, issue_id: str) -> list[ChecklistItem]:
"""
Use this request to get the parameters of an issue's checklist.
YC docs: https://cloud.yandex.com/en/docs/tracker/concepts/issues/get-checklist
"""
raw_response = await self._client.request(
method="GET",
uri=f"/issues/{issue_id}/checklistItems",
)
return [ChecklistItem(**raw_checklist_item) for raw_checklist_item in loads(raw_response)]

async def edit_checklist_item(
self,
issue_id: str,
checklist_item_id: str,
text: str,
checked: bool | None = None,
assignee: str | None = None,
deadline: Deadline | None = None,
) -> IssueWithChecklist:
"""
YC docs: https://cloud.yandex.com/en/docs/tracker/concepts/issues/edit-checklist
"""
raw_response = await self._client.request(
method="PATCH",
uri=f"/issues/{issue_id}/checklistItems/{checklist_item_id}",
payload=ChecklistItemEdit(
text=text,
checked=checked,
assignee=assignee,
deadline=deadline,
).model_dump(exclude_none=True, by_alias=True),
)
return IssueWithChecklist(**loads(raw_response))

async def delete_checklist(self, issue_id: str) -> IssueWithChecklist:
"""
YC docs: https://cloud.yandex.com/en/docs/tracker/concepts/issues/delete-checklist
"""
raw_response = await self._client.request(
method="DELETE",
uri=f"/issues/{issue_id}/checklistItems",
)
return IssueWithChecklist(**loads(raw_response))

async def delete_checklist_item(self, issue_id: str, checklist_item_id: str):
"""
YC docs: https://cloud.yandex.com/en/docs/tracker/concepts/issues/delete-checklist-item
"""
raw_response = await self._client.request(
method="DELETE",
uri=f"/issues/{issue_id}/checklistItems/{checklist_item_id}",
)
return IssueWithChecklist(**loads(raw_response))
5 changes: 0 additions & 5 deletions ya_tracker_client/domain/repositories/queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,6 @@ async def get_queue_fields(self, queue_id: str | int) -> list[QueueField]:
method="GET",
uri=f"/queues/{queue_id}/fields",
)
for raw_queue_field in loads(raw_response):
print(*raw_queue_field.items(), sep="\n")
print()
QueueField(**raw_queue_field)

return [QueueField(**raw_queue_field) for raw_queue_field in loads(raw_response)]

async def delete_queue(self, queue_id: str | int) -> None:
Expand Down
6 changes: 6 additions & 0 deletions ya_tracker_client/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from ya_tracker_client.utils.encoder import serialize_entity


__all__ = [
"serialize_entity",
]
32 changes: 32 additions & 0 deletions ya_tracker_client/utils/encoder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from datetime import datetime
from decimal import Decimal
from json import JSONEncoder, dumps
from uuid import UUID
from zoneinfo import ZoneInfo

from yarl import URL


class UpgradedJSONEncoder(JSONEncoder):
def default(self, entity):
if isinstance(entity, datetime):
if entity.tzinfo is None: # for YYYY-MM-DDThh:mm:ss.sss±hhmm format
entity = entity.replace(tzinfo=ZoneInfo("UTC"))
return entity.isoformat()

if isinstance(entity, Decimal) or isinstance(entity, UUID):
return str(entity)

if isinstance(entity, URL):
return str(entity)

return JSONEncoder.default(self, entity)


def serialize_entity(entity):
return dumps(entity, cls=UpgradedJSONEncoder)


__all__ = [
"serialize_entity",
]

0 comments on commit 7d9bfb4

Please sign in to comment.