Skip to content

Commit

Permalink
Merge branch 'main' into py312-aware-utc
Browse files Browse the repository at this point in the history
  • Loading branch information
ludeeus authored Aug 14, 2023
2 parents ef440c9 + 2cc1d45 commit 586dc78
Show file tree
Hide file tree
Showing 13 changed files with 59 additions and 43 deletions.
8 changes: 4 additions & 4 deletions aiogithubapi/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
from enum import Enum

class StrEnum(str, Enum):
"""Workaround untill lowest version is Python3.11."""
"""Workaround until lowest version is Python3.11."""

def __str__(self) -> str:
return str(self.value)

class IntEnum(int, Enum):
"""Workaround untill lowest version is Python3.11."""
"""Workaround until lowest version is Python3.11."""


GenericType = TypeVar("GenericType")
Expand All @@ -36,7 +36,7 @@ class IntEnum(int, Enum):
}

# This is the default user agent,
# but it is adviced to use your own when building out your application
# but it is advised to use your own when building out your application
DEFAULT_USER_AGENT = f"aiogithubapi/{PROJECT_VERSION}"

# https://docs.github.com/en/rest/overview/api-versions
Expand Down Expand Up @@ -93,7 +93,7 @@ class GitHubClientKwarg(StrEnum):
HEADERS:
Used to set the base headers for all requests.
BASE_URL:
Used to ovveride the base url for all requests. Defaults to https://api.github.com .
Used to override the base url for all requests. Defaults to https://api.github.com .
TIMEOUT:
Used to set the timeout for all requests. Defaults to 20
CLIENT_NAME:
Expand Down
10 changes: 6 additions & 4 deletions aiogithubapi/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ async def register(
self,
**kwargs: Dict[GitHubRequestKwarg, Any],
) -> GitHubResponseModel[GitHubLoginDeviceModel]:
"""Register the device and return a object that contains the user code for authorization."""
"""Register the device and return an object that contains the user code for authorization."""
response = await self._client.async_call_api(
endpoint=OAUTH_DEVICE_LOGIN_PATH,
**{
Expand Down Expand Up @@ -155,9 +155,11 @@ async def activation(
if error := response.data.get("error"):
self.logger.debug(response.data.get("error_description"))
if error in (DeviceFlowError.AUTHORIZATION_PENDING, DeviceFlowError.SLOW_DOWN):
await asyncio.sleep(
(self._interval or 1) + (5 if error == DeviceFlowError.SLOW_DOWN else 0)
)
if interval := response.data.get("interval"):
self.logger.info(
"Got new interval instruction of %s from the API", interval
)
await asyncio.sleep(interval or self._interval or 5)
else:
raise GitHubException(response.data.get("error_description"))
else:
Expand Down
6 changes: 3 additions & 3 deletions aiogithubapi/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

class GitHubException(BaseException):
"""
This is raised when unknown exceptions occour.
This is raised when unknown exceptions occur.
And it's used as a base for all other exceptions
so if you want to catch all GitHub related errors
Expand All @@ -28,7 +28,7 @@ class GitHubPayloadException(GitHubException):


class GitHubGraphQLException(GitHubException):
"""This is raised when the response from GraphQL calls have erros."""
"""This is raised when the response from GraphQL calls have errors."""


class GitHubPermissionException(GitHubException):
Expand All @@ -40,4 +40,4 @@ class GitHubNotModifiedException(GitHubException):


class GitHubAuthenticationException(GitHubException):
"""This is raised when we recieve an authentication issue."""
"""This is raised when we receive an authentication issue."""
2 changes: 1 addition & 1 deletion aiogithubapi/legacy/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ async def __aexit__(self, *exc_info) -> None:
await self._close()

async def async_register_device(self) -> AIOGitHubAPILoginDevice:
"""Register the device and return a object that contains the user code for authorization."""
"""Register the device and return an object that contains the user code for authorization."""
params = {"client_id": self.client_id, "scope": self.scope}
response = await async_call_api(
session=self.session,
Expand Down
8 changes: 4 additions & 4 deletions aiogithubapi/legacy/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ async def get_repo(
repo: str,
etag: Optional[str] = None,
) -> AIOGitHubAPIRepository:
"""Retrun AIOGitHubAPIRepository object."""
"""Return AIOGitHubAPIRepository object."""
_endpoint = f"/repos/{repo}"
_headers = {"Accept": ACCEPT_HEADERS["preview"]}
if etag:
Expand All @@ -77,7 +77,7 @@ async def get_org_repos(
self, org: str, page: int = 1, etag: Optional[str] = None
) -> List[AIOGitHubAPIRepository]:
"""
Retrun a list of AIOGitHubAPIRepository objects.
Return a list of AIOGitHubAPIRepository objects.
param | required | Default | description
-- | -- | -- | --
Expand All @@ -104,15 +104,15 @@ async def graphql(self, query: str, variables: dict = {}) -> dict:
return response.data.get("data")

async def get_rate_limit(self) -> dict:
"""Retrun current rate limits."""
"""Return current rate limits."""
_endpoint = "/rate_limit"

await self.client.get(endpoint=_endpoint)
return self.client.ratelimits.__dict__

async def render_markdown(self, content: str, etag: Optional[str] = None) -> str:
"""
Retrun AIOGitHubAPIRepository object.
Return AIOGitHubAPIRepository object.
[API Docs](https://docs.github.com/en/rest/reference/markdown#render-a-markdown-document-in-raw-mode)
Expand Down
8 changes: 4 additions & 4 deletions aiogithubapi/namespaces/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ async def subscribe(
`event_callback`
An async funtion that will be called when new events come in,
An async function that will be called when new events come in,
the event will be passed as the first argument.
`error_callback` (Optional)
An async funtion that will be called when errors occour,
An async function that will be called when errors occur,
the exception that where raised will be passed.
https://docs.github.com/en/rest/reference/activity#list-public-events
Expand Down Expand Up @@ -202,12 +202,12 @@ async def subscribe(
`event_callback`
An async funtion that will be called when new events come in,
An async function that will be called when new events come in,
the event will be passed as the first argument.
`error_callback` (Optional)
An async funtion that will be called when errors occour,
An async function that will be called when errors occur,
the exception that where raised will be passed.
https://docs.github.com/en/rest/reference/activity#list-repository-events
Expand Down
12 changes: 6 additions & 6 deletions aiogithubapi/objects/repository/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def owner(self) -> AIOGitHubAPIUsersUser:
async def get_contents(
self, path: str, ref: str or None = None, etag: Optional[str] = None
) -> list["AIOGitHubAPIRepositoryContent"] or "AIOGitHubAPIRepositoryContent":
"""Retrun a list of repository content objects."""
"""Return a list of repository content objects."""
_endpoint = f"/repos/{self.full_name}/contents/{path}"
_params = {"path": path}
_headers = {}
Expand All @@ -115,7 +115,7 @@ async def get_contents(
async def get_tree(
self, ref: str or None = None, etag: Optional[str] = None
) -> list["AIOGitHubAPIRepositoryTreeContent"] or list:
"""Retrun a list of repository tree objects."""
"""Return a list of repository tree objects."""
if ref is None:
raise AIOGitHubAPIException("Missing ref")
_endpoint = f"/repos/{self.full_name}/git/trees/{ref}"
Expand All @@ -134,7 +134,7 @@ async def get_tree(
async def get_rendered_contents(
self, path: str, ref: str or None = None, etag: Optional[str] = None
) -> str:
"""Retrun a redered representation of a file."""
"""Return a rendered representation of a file."""
_endpoint = f"/repos/{self.full_name}/contents/{path}"
_headers = {"Accept": "application/vnd.github.v3.html"}
_params = {"path": path}
Expand All @@ -152,7 +152,7 @@ async def get_rendered_contents(
async def get_releases(
self, prerelease: bool = False, returnlimit: int = 5, etag: Optional[str] = None
) -> list["AIOGitHubAPIRepositoryRelease"] or list:
"""Retrun a list of repository release objects."""
"""Return a list of repository release objects."""
_endpoint = f"/repos/{self.full_name}/releases"
_headers = {}
if etag:
Expand All @@ -172,7 +172,7 @@ async def get_releases(
return contents

async def set_last_commit(self, etag: Optional[str] = None) -> None:
"""Retrun a list of repository release objects."""
"""Return a list of repository release objects."""
_endpoint = f"/repos/{self.full_name}/branches/{self.default_branch}"
_headers = {}
if etag:
Expand All @@ -181,7 +181,7 @@ async def set_last_commit(self, etag: Optional[str] = None) -> None:
self._last_commit = response.data["commit"]["sha"][0:7]

async def get_last_commit(self, etag: Optional[str] = None) -> None:
"""Retrun a list of repository release objects."""
"""Return a list of repository release objects."""
_endpoint = f"/repos/{self.full_name}/branches/{self.default_branch}"
_headers = {}
if etag:
Expand Down
2 changes: 1 addition & 1 deletion aiogithubapi/objects/repository/issue/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@


class AIOGitHubAPIRepositoryIssue(AIOGitHubAPIBaseClient):
"""Issue commment user GitHub API implementation."""
"""Issue comment user GitHub API implementation."""

@property
def html_url(self):
Expand Down
2 changes: 1 addition & 1 deletion aiogithubapi/objects/repository/issue/comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


class AIOGitHubAPIRepositoryIssueCommentUser(AIOGitHubAPIUsersUser):
"""Issue commment user GitHub API implementation."""
"""Issue comment user GitHub API implementation."""

@property
def login(self):
Expand Down
4 changes: 2 additions & 2 deletions documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ asyncio.get_event_loop().run_until_complete(with_token())
## Usage notes

- When constructing the client, you should pass a `client_name` parameter, or a user agent string.
- Each response object has a `etag` attribute, which can be used to make subsequent requests.
- If you pass a `etag` parameter, and the API returns a 304 Not Modified, the client will raise `GitHubNotModifiedException`
- Each response object has an `etag` attribute, which can be used to make subsequent requests.
- If you pass an `etag` parameter, and the API returns a 304 Not Modified, the client will raise `GitHubNotModifiedException`
14 changes: 7 additions & 7 deletions tests/client/test_construction.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


@pytest.mark.asyncio
async def test_client_constrution_defaults(
async def test_client_construction_defaults(
client_session: ClientSession, caplog: pytest.CaptureFixture
):
client = GitHubClient(session=client_session)
Expand All @@ -31,7 +31,7 @@ async def test_client_constrution_defaults(


@pytest.mark.asyncio
async def test_client_constrution_with_token(client_session: ClientSession):
async def test_client_construction_with_token(client_session: ClientSession):
client = GitHubClient(session=client_session, token=TOKEN)
base_request_data = client._base_request_data
assert base_request_data.token == TOKEN
Expand All @@ -42,7 +42,7 @@ async def test_client_constrution_with_token(client_session: ClientSession):


@pytest.mark.asyncio
async def test_client_constrution_with_api_version(client_session: ClientSession):
async def test_client_construction_with_api_version(client_session: ClientSession):
client = GitHubClient(session=client_session, token=TOKEN, api_version="3000-01-01")
base_request_data = client._base_request_data
assert base_request_data.token == TOKEN
Expand All @@ -54,14 +54,14 @@ async def test_client_constrution_with_api_version(client_session: ClientSession


@pytest.mark.asyncio
async def test_client_constrution_with_kwargs_timeout(client_session: ClientSession):
async def test_client_construction_with_kwargs_timeout(client_session: ClientSession):
client = GitHubClient(session=client_session, **{GitHubClientKwarg.TIMEOUT: 10})
base_request_data = client._base_request_data
assert base_request_data.timeout == 10


@pytest.mark.asyncio
async def test_client_constrution_with_kwargs_base_url(client_session: ClientSession):
async def test_client_construction_with_kwargs_base_url(client_session: ClientSession):
client = GitHubClient(
session=client_session, **{GitHubClientKwarg.BASE_URL: "https://example.com"}
)
Expand All @@ -70,7 +70,7 @@ async def test_client_constrution_with_kwargs_base_url(client_session: ClientSes


@pytest.mark.asyncio
async def test_client_constrution_with_kwargs_headers(client_session: ClientSession):
async def test_client_construction_with_kwargs_headers(client_session: ClientSession):
client = GitHubClient(
session=client_session, **{GitHubClientKwarg.HEADERS: {"User-Agent": "test/client"}}
)
Expand All @@ -79,7 +79,7 @@ async def test_client_constrution_with_kwargs_headers(client_session: ClientSess


@pytest.mark.asyncio
async def test_client_constrution_with_kwargs_client_name(client_session: ClientSession):
async def test_client_construction_with_kwargs_client_name(client_session: ClientSession):
client = GitHubClient(
session=client_session, **{GitHubClientKwarg.CLIENT_NAME: "test_client/1.2.3"}
)
Expand Down
6 changes: 3 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ def asyncio_sleep():

@pytest.fixture()
def mock_requests():
"""Return a new mock request instanse."""
"""Return a new mock request instance."""
yield MockedRequests()


@pytest.fixture()
def response():
"""Return a new mock response instanse."""
"""Return a new mock response instance."""
yield MockResponse()


@pytest.fixture()
def mock_response():
"""Return a new mock response instanse."""
"""Return a new mock response instance."""
yield MockResponse()


Expand Down
20 changes: 17 additions & 3 deletions tests/device/test_device_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ async def test_wait_for_confirmation(
"error": DeviceFlowError.AUTHORIZATION_PENDING,
"error_description": "Pending user authorization",
},
{
"error": DeviceFlowError.SLOW_DOWN,
"error_description": "Too many requests have been made in the same timeframe.",
"interval": 20
},
{
"error": DeviceFlowError.AUTHORIZATION_PENDING,
"error_description": "Pending user authorization",
Expand All @@ -97,18 +102,27 @@ async def test_wait_for_confirmation(
]
response = await github_device_api.activation(device_code=DEVICE_CODE)
assert response.status == 200
assert mock_requests.called == 4
assert asyncio_sleep.call_count == 3
assert mock_requests.called == 5
assert asyncio_sleep.call_count == 4

# Use default interval
assert asyncio_sleep.call_args_list[-3][0][0] == 1
# Use new interval from API
assert asyncio_sleep.call_args_list[-2][0][0] == 20
# Use default interval
assert asyncio_sleep.call_args_list[-1][0][0] == 1

assert mock_requests.last_request["url"] == "https://github.com/login/oauth/access_token"
assert "Pending user authorization" in caplog.text
assert "Got new interval instruction of 20 from the API" in caplog.text


@pytest.mark.asyncio
async def test_error_while_waiting(
github_device_api: GitHubDeviceAPI,
mock_response: MockResponse,
):
mock_response.mock_data = {"error": "any", "error_description": "Any error message"}
mock_response.mock_data = {"error": "any",
"error_description": "Any error message"}
with pytest.raises(GitHubException, match="Any error message"):
await github_device_api.activation(device_code=DEVICE_CODE)

0 comments on commit 586dc78

Please sign in to comment.