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: add comments support #27

Merged
merged 3 commits into from
Sep 30, 2023
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 .github/workflows/code-check.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Checks
name: Linters and tests
on: [pull_request]

jobs:
Expand Down
66 changes: 65 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,71 @@

Async Yandex Tracker Client based on aiohttp and pydantic (v2)

# Current library capabilities
[![Python](https://img.shields.io/badge/python-^3.11-blue)](https://www.python.org/)
[![Code linter: ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v1.json)](https://github.com/charliermarsh/ruff)
[![Linters](https://github.com/danfimov/ya_tracker_client/actions/workflows/code-check.yml/badge.svg)](https://github.com/danfimov/ya_tracker_client/actions/workflows/code-check.yml)

---

API docs: https://cloud.yandex.com/en/docs/tracker/about-api

## Installation

```shell
pip install ya_tracker_clint
```

## Usage

```python
import os
from asyncio import run

from dotenv import load_dotenv

from ya_tracker_client import YaTrackerClient


load_dotenv()
# from registered application at Yandex OAuth - https://oauth.yandex.ru/
API_TOKEN = os.getenv("API_TOKEN")
# from admin panel at Yandex Tracker - https://tracker.yandex.ru/admin/orgs
API_ORGANISATION_ID = os.getenv("API_ORGANISATION_ID")


async def main() -> None:
# init client
client = YaTrackerClient(
organisation_id=API_ORGANISATION_ID,
oauth_token=API_TOKEN,
)

# create issue
new_issue = await client.create_issue('New issue', 'TRACKER-QUEUE')

# get issue
issue = await client.get_issue('KEY-1')

# update issue (just pass kwargs)
issue = await client.edit_issue('KEY-1', description='Hello World')

# don't forget to close tracker on app shutdown
await client.stop()


if __name__ == "__main__":
run(main())
```


## Explanations about naming

- All `self` properties renamed to `url` cause it's incompatible with Python;
- All `camelCase` properties renamed to `pythonic_case`;
- All datetime values converted to python's `datetime.datetime` objects;
- Methods named by author, cause Yandex API has no clear method names.

## Current library capabilities

- Working with queues
- Getting information about issues, priorities and transitions
Expand Down
1 change: 1 addition & 0 deletions examples/get_test_entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ async def main() -> None:
await client.get_worklog("TRACKER-1")
await client.get_worklog_records_by_parameters(me.login)
await client.get_attachments_list('TRACKER-1')
await client.get_issue_comments('TRACKER-1')

await client.stop()

Expand Down
35 changes: 35 additions & 0 deletions ya_tracker_client/domain/entities/comment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from datetime import datetime

from pydantic import Field

from ya_tracker_client.domain.entities.base import AbstractEntity
from ya_tracker_client.domain.entities.mailing_list import MailingList
from ya_tracker_client.domain.entities.user import UserShort


class Comment(AbstractEntity):
url: str
id: int
long_id: str
text: str
created_by: UserShort
created_at: datetime
updated_by: UserShort
updated_at: datetime
summonees: list[UserShort] = Field(default_factory=list)
maillistsummonees: list[MailingList] = Field(default_factory=list)
version: int
type: str = Field(examples=["standard", "incoming", "outcoming"])
transport: str = Field(examples=["internal", "email"])


class CommentCreate(AbstractEntity):
text: str
attachment_ids: list[str] | None = None
summonees: list[UserShort | str] | None = None
maillistsummonees: list[str] | None = None


class CommentEdit(AbstractEntity):
text: str
attachment_ids: list[str] | None = None
7 changes: 7 additions & 0 deletions ya_tracker_client/domain/entities/mailing_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from ya_tracker_client.domain.entities.base import AbstractEntity


class MailingList(AbstractEntity):
url: str
id: str
display: str
4 changes: 3 additions & 1 deletion ya_tracker_client/domain/repositories/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from ya_tracker_client.domain.repositories.attachment import AttachmentRepository
from ya_tracker_client.domain.repositories.checklist import ChecklistRepository
from ya_tracker_client.domain.repositories.comment import CommentRepository
from ya_tracker_client.domain.repositories.component import ComponentRepository
from ya_tracker_client.domain.repositories.issue import IssueRepository
from ya_tracker_client.domain.repositories.issue_relationship import IssueRelationshipRepository
Expand All @@ -11,10 +12,11 @@
__all__ = [
"AttachmentRepository",
"ChecklistRepository",
"CommentRepository",
"ComponentRepository",
"IssueRelationshipRepository",
"IssueRepository",
"QueueRepository",
"WorklogRepository",
"UserRepository",
"WorklogRepository",
]
6 changes: 3 additions & 3 deletions ya_tracker_client/domain/repositories/attachment.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
class AttachmentRepository(EntityRepository):
async def get_attachments_list(self, issue_id: str) -> list[Attachment]:
"""
Use this request to get a list of files attached to an issue and to comments below it.
Use this method to get a list of files attached to an issue and to comments below it.

YC docs: https://cloud.yandex.com/en/docs/tracker/concepts/issues/get-attachments-list
"""
Expand All @@ -26,7 +26,7 @@ async def download_attachment(
filename: str,
) -> bytes:
"""
Use this request to download files attached to issues.
Use this method to download files attached to issues.

YC docs: https://cloud.yandex.com/en/docs/tracker/concepts/issues/get-attachment
"""
Expand Down Expand Up @@ -78,7 +78,7 @@ async def upload_temp_file(
"""
Upload temporary file.

Use this request to upload a file to Tracker first, and then
Use this method to upload a file to Tracker first, and then
attach it when creating an issue or adding a comment.

YC docs: https://cloud.yandex.com/en/docs/tracker/concepts/issues/temp-attachment
Expand Down
81 changes: 81 additions & 0 deletions ya_tracker_client/domain/repositories/comment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from ya_tracker_client.domain.entities.comment import Comment, CommentCreate, CommentEdit
from ya_tracker_client.domain.entities.user import UserShort
from ya_tracker_client.domain.repositories.base import EntityRepository


class CommentRepository(EntityRepository):
async def add_comment(
self,
issue_id: str,
text: str,
attachment_ids: list[str] | None = None,
summonees: list[str | UserShort] | None = None,
maillist_summonees: list[str] | None = None,
is_add_to_followers: bool | None = None,
) -> Comment:
"""
Use this method to add a comment to an issue.

YC docs: https://cloud.yandex.com/en/docs/tracker/concepts/issues/add-comment
"""
raw_response = await self._client.request(
method="POST",
uri=f"/issues/{issue_id}/comments",
payload=CommentCreate(
text=text,
attachment_ids=attachment_ids,
summonees=summonees,
maillist_summonees=maillist_summonees,
).model_dump(exclude_none=True, by_alias=True),
params={"is_add_to_followers": is_add_to_followers} if is_add_to_followers is not None else None,
)
return self._decode(raw_response, Comment)

async def get_issue_comments(self, issue_id: str) -> list[Comment]:
"""
Use this method to get a list of comments on an issue.

YC docs: https://cloud.yandex.com/en/docs/tracker/concepts/issues/get-comments
"""
raw_response = await self._client.request(
method="GET",
uri=f"/issues/{issue_id}/comments",
)
return self._decode(raw_response, Comment, plural=True)

async def edit_comment(
self,
issue_id: str,
comment_id: str | int,
text: str,
attachment_ids: list[str] | None = None,
) -> Comment:
"""
Use this method to edit comments.

YC docs: https://cloud.yandex.com/en/docs/tracker/concepts/issues/edit-comment
"""
raw_response = await self._client.request(
method="PATCH",
uri=f"/issues/{issue_id}/comments/{comment_id}",
payload=CommentEdit(
text=text,
attachment_ids=attachment_ids,
).model_dump(exclude_none=True, by_alias=True),
)
return self._decode(raw_response, Comment)

async def delete_comment(
self,
issue_id: str,
comment_id: str | int,
) -> None:
"""
Use this method to delete issue comments.

YC docs: https://cloud.yandex.com/en/docs/tracker/concepts/issues/delete-comment
"""
await self._client.request(
method="DELETE",
uri=f"/issues/{issue_id}/comments/{comment_id}",
)
2 changes: 2 additions & 0 deletions ya_tracker_client/service/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from ya_tracker_client.domain.repositories import (
AttachmentRepository,
ChecklistRepository,
CommentRepository,
ComponentRepository,
IssueRelationshipRepository,
IssueRepository,
Expand All @@ -13,6 +14,7 @@

class YaTrackerClient(
AttachmentRepository,
CommentRepository,
ChecklistRepository,
ComponentRepository,
IssueRelationshipRepository,
Expand Down
Loading