Skip to content

Commit d4b96c8

Browse files
ludeeusCopilot
andauthored
Add GitHub notifications namespace (#477)
* Add GitHub notifications namespace * Apply review feedback: use consistent type annotations in notifications namespace (#478) * Initial plan * Apply review feedback: use consistent type annotations in notifications namespace Co-authored-by: ludeeus <15093472+ludeeus@users.noreply.github.com> * Update aiogithubapi/namespaces/notifications.py * Update aiogithubapi/namespaces/notifications.py --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: ludeeus <15093472+ludeeus@users.noreply.github.com> Co-authored-by: Joakim Sørensen <joasoe@proton.me> --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
1 parent beb489c commit d4b96c8

File tree

6 files changed

+174
-0
lines changed

6 files changed

+174
-0
lines changed

aiogithubapi/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
from .models.login_oauth import GitHubLoginOauthModel
4646
from .models.meta import GitHubMetaModel
4747
from .models.milestone import GitHubMilestoneModel
48+
from .models.notification import GitHubNotificationModel
4849
from .models.organization import GitHubOrganizationMinimalModel, GitHubOrganizationModel
4950
from .models.owner import GitHubOwnerModel
5051
from .models.permissions import GitHubPermissionsModel

aiogithubapi/github.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from .models.meta import GitHubMetaModel
1515
from .models.rate_limit import GitHubRateLimitModel
1616
from .models.response import GitHubResponseModel
17+
from .namespaces.notifications import GitHubNotificationsNamespace
1718
from .namespaces.orgs import GitHubOrgsNamespace
1819
from .namespaces.projects import GitHubBaseProjectsNamespace
1920
from .namespaces.repos import GitHubReposNamespace
@@ -73,12 +74,18 @@ def __init__(
7374
self._client = GitHubClient(token=token, session=session, api_version=api_version, **kwargs)
7475

7576
# Namespaces
77+
self._notifications = GitHubNotificationsNamespace(self._client)
7678
self._repos = GitHubReposNamespace(self._client)
7779
self._user = GitHubUserNamespace(self._client)
7880
self._users = GitHubUsersNamespace(self._client)
7981
self._orgs = GitHubOrgsNamespace(self._client)
8082
self._projects = GitHubBaseProjectsNamespace(self._client)
8183

84+
@property
85+
def notifications(self) -> GitHubNotificationsNamespace:
86+
"""Property to access the notifications namespace."""
87+
return self._notifications
88+
8289
@property
8390
def repos(self) -> GitHubReposNamespace:
8491
"""Property to access the repos namespace."""
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""GitHub notification models"""
2+
3+
from __future__ import annotations
4+
5+
from typing import Any, Dict
6+
7+
from .base import GitHubDataModelBase
8+
from .repository import GitHubRepositoryModel
9+
10+
11+
class _Subject(GitHubDataModelBase):
12+
"""Notification subject."""
13+
14+
title: str | None = None
15+
url: str | None = None
16+
latest_comment_url: str | None = None
17+
type: str | None = None
18+
19+
20+
class GitHubNotificationModel(GitHubDataModelBase):
21+
"""
22+
GitHub notification data class.
23+
24+
https://docs.github.com/en/rest/activity/notifications
25+
"""
26+
27+
id: str | None = None
28+
repository: GitHubRepositoryModel | None = None
29+
subject: _Subject | None = None
30+
reason: str | None = None
31+
unread: bool | None = None
32+
updated_at: str | None = None
33+
last_read_at: str | None = None
34+
url: str | None = None
35+
subscription_url: str | None = None
36+
37+
def _generate_repository(self, data: Dict[str, Any] | None) -> GitHubRepositoryModel:
38+
"""Generate repository data."""
39+
return GitHubRepositoryModel(data) if data else None
40+
41+
def _generate_subject(self, data: Dict[str, Any] | None) -> _Subject:
42+
"""Generate subject data."""
43+
return _Subject(data) if data else None
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
"""
2+
Methods for the notifications namespace
3+
4+
https://docs.github.com/en/rest/activity/notifications
5+
"""
6+
7+
from __future__ import annotations
8+
9+
from typing import Any
10+
11+
from ..const import GitHubRequestKwarg
12+
from ..models.notification import GitHubNotificationModel
13+
from ..models.response import GitHubResponseModel
14+
from .base import BaseNamespace
15+
16+
17+
class GitHubNotificationsNamespace(BaseNamespace):
18+
"""Methods for the notifications namespace"""
19+
20+
async def list(
21+
self,
22+
*,
23+
all: bool = False,
24+
participating: bool = False,
25+
since: str | None = None,
26+
before: str | None = None,
27+
page: int = 1,
28+
per_page: int = 50,
29+
params: dict[str, str] | None = None,
30+
**kwargs: Any,
31+
) -> GitHubResponseModel[list[GitHubNotificationModel]]:
32+
"""
33+
List notifications for the authenticated user
34+
35+
https://docs.github.com/en/rest/activity/notifications#list-notifications-for-the-authenticated-user
36+
"""
37+
request_params = {}
38+
if all:
39+
request_params["all"] = "true"
40+
if participating:
41+
request_params["participating"] = "true"
42+
if since:
43+
request_params["since"] = since
44+
if before:
45+
request_params["before"] = before
46+
if page != 1:
47+
request_params["page"] = str(page)
48+
if per_page != 50:
49+
request_params["per_page"] = str(per_page)
50+
if params:
51+
request_params.update(params)
52+
53+
response = await self._client.async_call_api(
54+
endpoint="/notifications",
55+
params=request_params,
56+
**kwargs,
57+
)
58+
response.data = [GitHubNotificationModel(data) for data in response.data]
59+
return response

tests/fixtures/notifications.json

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
[
2+
{
3+
"id": "1",
4+
"repository": {
5+
"id": 1296269,
6+
"node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
7+
"name": "Hello-World",
8+
"full_name": "octocat/Hello-World",
9+
"owner": {
10+
"login": "octocat",
11+
"id": 1,
12+
"node_id": "MDQ6VXNlcjE=",
13+
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
14+
"gravatar_id": "",
15+
"url": "https://api.github.com/users/octocat",
16+
"html_url": "https://github.com/octocat",
17+
"type": "User",
18+
"site_admin": false
19+
},
20+
"private": false,
21+
"html_url": "https://github.com/octocat/Hello-World",
22+
"description": "This your first repo!",
23+
"fork": false,
24+
"url": "https://api.github.com/repos/octocat/Hello-World"
25+
},
26+
"subject": {
27+
"title": "Greetings",
28+
"url": "https://api.github.com/repos/octokit/octokit.rb/issues/123",
29+
"latest_comment_url": "https://api.github.com/repos/octokit/octokit.rb/issues/comments/123",
30+
"type": "Issue"
31+
},
32+
"reason": "subscribed",
33+
"unread": true,
34+
"updated_at": "2014-11-07T22:01:45Z",
35+
"last_read_at": "2014-11-07T22:01:45Z",
36+
"url": "https://api.github.com/notifications/threads/1",
37+
"subscription_url": "https://api.github.com/notifications/threads/1/subscription"
38+
}
39+
]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""Test notifications namespace."""
2+
# pylint: disable=missing-docstring
3+
import pytest
4+
5+
from aiogithubapi import GitHubAPI
6+
from aiogithubapi.models.notification import GitHubNotificationModel
7+
8+
from tests.common import (
9+
MockedRequests,
10+
)
11+
12+
13+
@pytest.mark.asyncio
14+
async def test_list_notifications(github_api: GitHubAPI, mock_requests: MockedRequests):
15+
response = await github_api.notifications.list()
16+
assert response.status == 200
17+
assert isinstance(response.data, list)
18+
assert len(response.data) == 1
19+
assert isinstance(response.data[0], GitHubNotificationModel)
20+
assert response.data[0].id == "1"
21+
assert response.data[0].subject.title == "Greetings"
22+
assert response.data[0].reason == "subscribed"
23+
assert response.data[0].unread is True
24+
assert mock_requests.called == 1
25+
assert mock_requests.last_request["url"] == "https://api.github.com/notifications"

0 commit comments

Comments
 (0)