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

feat: checklists support #23

Merged
merged 3 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
feat: add checklist support
  • Loading branch information
danfimov committed Sep 28, 2023
commit 7d9bfb4f2d6823923c1a7c0ed26246293bdc04c1
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",
]
Loading