Skip to content
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
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ async with AppClient(app_id, privkey, owner=owner, repositories=["simple-github"
resp = await session.get("/octocat")
```

The `AppClient` can be used in both sync and async contexts. If a running async
loop is found, an object with `await`able method will be returned, otherwise a
normal synchronous object with the same methods will be provided.

### Authenticate as a Github App

You can also authenticate as the app itself. This is mainly only useful for
Expand Down Expand Up @@ -126,6 +130,12 @@ easily be called from synchronous code with
return asyncio.run(inst_auth.get_token())
```

For convenience, the `AppClient` provides a `get_token()` methods hiding those details.

```python
token = await AppClient(app_id, privkey, owner=owner, repositories=["simple-github"]).get_token()
```

The returned token (`ghs_XXX`) can be used directly to authenticate git+http
operations as the `git` user.

Expand Down
10 changes: 8 additions & 2 deletions src/simple_github/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ def close(self) -> None:
if self._gql_client:
self._gql_client.close_sync()

def get_token(self) -> str:
return asyncio.run(self.auth.get_token())

def _get_gql_session(self) -> SyncClientSession:
"""Return an AIOHTTP session.

Expand All @@ -103,7 +106,7 @@ def _get_gql_session(self) -> SyncClientSession:
Returns:
aiohttp.ClientSession: An AIOHTTP session object.
"""
token = asyncio.run(self.auth.get_token())
token = self.get_token()

if token == self._prev_token:
assert isinstance(self._gql_session, SyncClientSession)
Expand Down Expand Up @@ -250,6 +253,9 @@ async def close(self) -> None:
if self._gql_client:
await self._gql_client.close_async()

async def get_token(self) -> str:
return await self.auth.get_token()

async def _get_gql_session(self) -> ReconnectingAsyncClientSession:
"""Return an AIOHTTP session.

Expand All @@ -259,7 +265,7 @@ async def _get_gql_session(self) -> ReconnectingAsyncClientSession:
Returns:
aiohttp.ClientSession: An AIOHTTP session object.
"""
token = await self.auth.get_token()
token = await self.get_token()
if token == self._prev_token:
assert isinstance(self._gql_session, ReconnectingAsyncClientSession)
return self._gql_session
Expand Down
19 changes: 19 additions & 0 deletions test/test_simple_github.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,25 @@ async def test_app_installation_client(aioresponses, privkey):
assert result == {"foo": "bar"}


@pytest.mark.asyncio
async def test_app_installation_client_get_token(aioresponses, privkey):
owner = "owner"
inst_id = 1

aioresponses.get(
f"{GITHUB_API_ENDPOINT}/app/installations",
status=200,
payload=[{"id": inst_id, "account": {"login": owner}}],
)
aioresponses.post(
f"{GITHUB_API_ENDPOINT}/app/installations/{inst_id}/access_tokens",
status=200,
payload={"token": "789"},
)

assert await AppClient(id=123, privkey=privkey, owner=owner).get_token() == "789"


@pytest.mark.parametrize(
"env,expected_client",
(
Expand Down