Skip to content

Commit c474560

Browse files
authored
🐛 fix concurrency context error
1 parent 32e7165 commit c474560

File tree

2 files changed

+84
-73
lines changed

2 files changed

+84
-73
lines changed

nonebot/adapters/github/bot.py

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import re
2+
from contextvars import ContextVar
23
from typing_extensions import Self
34
from contextlib import asynccontextmanager
45
from typing import (
@@ -132,14 +133,16 @@ def __init__(self, adapter: "Adapter", app: Union[GitHubApp, OAuthApp]):
132133
super().__init__(adapter, app.id)
133134
self.app = app
134135
self._github: GitHub
135-
self._ctx_github: Optional[GitHub] = None
136+
self._ctx_github: ContextVar[Optional[GitHub]] = ContextVar(
137+
"ctx_github", default=None
138+
)
136139

137140
def __getattr__(self, name: str) -> APIContext:
138141
return APIContext(self, (name,))
139142

140143
@property
141144
def github(self) -> GitHub:
142-
return self._ctx_github or self._github
145+
return self._ctx_github.get() or self._github
143146

144147
async def handle_event(self, event: Event) -> None:
145148
await handle_event(self, event)
@@ -167,27 +170,29 @@ def __init__(self, adapter: "Adapter", app: OAuthApp):
167170
async def as_web_user(
168171
self, code: str, redirect_uri: Optional[str] = None
169172
) -> AsyncGenerator[Self, None]:
170-
if self._ctx_github is not None:
173+
if self._ctx_github.get() is not None:
171174
raise RuntimeError("Can not enter context twice.")
172-
self._ctx_github = self._github.with_auth(
173-
self._github.auth.as_web_user(code, redirect_uri)
175+
self._ctx_github.set(
176+
g := self._github.with_auth(
177+
self._github.auth.as_web_user(code, redirect_uri)
178+
)
174179
)
175-
async with self._ctx_github:
176-
try:
180+
try:
181+
async with g:
177182
yield self
178-
finally:
179-
self._ctx_github = None
183+
finally:
184+
self._ctx_github.set(None)
180185

181186
@asynccontextmanager
182187
async def as_user(self, token: str) -> AsyncGenerator[Self, None]:
183-
if self._ctx_github is not None:
188+
if self._ctx_github.get() is not None:
184189
raise RuntimeError("Can not enter context twice.")
185-
self._ctx_github = self._github.with_auth(TokenAuthStrategy(token))
186-
async with self._ctx_github:
187-
try:
190+
self._ctx_github.set(g := self._github.with_auth(TokenAuthStrategy(token)))
191+
try:
192+
async with g:
188193
yield self
189-
finally:
190-
self._ctx_github = None
194+
finally:
195+
self._ctx_github.set(None)
191196

192197
@overrides(Bot)
193198
async def handle_event(self, event: Event) -> None:
@@ -218,14 +223,16 @@ async def _get_self_info(self):
218223

219224
@asynccontextmanager
220225
async def as_oauth_app(self) -> AsyncGenerator[Self, None]:
221-
if self._ctx_github is not None:
226+
if self._ctx_github.get() is not None:
222227
raise RuntimeError("Can not enter context twice.")
223-
self._ctx_github = self._github.with_auth(self._github.auth.as_oauth_app())
224-
async with self._ctx_github:
225-
try:
228+
self._ctx_github.set(
229+
g := self._github.with_auth(self._github.auth.as_oauth_app())
230+
)
231+
try:
232+
async with g:
226233
yield self
227-
finally:
228-
self._ctx_github = None
234+
finally:
235+
self._ctx_github.set(None)
229236

230237
@asynccontextmanager
231238
async def as_installation(
@@ -235,44 +242,48 @@ async def as_installation(
235242
repository_ids: Union[Unset, List[int]] = UNSET,
236243
permissions: Union[Unset, "AppPermissionsType"] = UNSET,
237244
) -> AsyncGenerator[Self, None]:
238-
if self._ctx_github is not None:
245+
if self._ctx_github.get() is not None:
239246
raise RuntimeError("Can not enter context twice.")
240-
self._ctx_github = self._github.with_auth(
241-
self._github.auth.as_installation(
242-
installation_id, repositories, repository_ids, permissions
247+
self._ctx_github.set(
248+
g := self._github.with_auth(
249+
self._github.auth.as_installation(
250+
installation_id, repositories, repository_ids, permissions
251+
)
243252
)
244253
)
245-
async with self._ctx_github:
246-
try:
254+
try:
255+
async with g:
247256
yield self
248-
finally:
249-
self._ctx_github = None
257+
finally:
258+
self._ctx_github.set(None)
250259

251260
@asynccontextmanager
252261
async def as_web_user(
253262
self, code: str, redirect_uri: Optional[str] = None
254263
) -> AsyncGenerator[Self, None]:
255-
if self._ctx_github is not None:
264+
if self._ctx_github.get() is not None:
256265
raise RuntimeError("Can not enter context twice.")
257-
self._ctx_github = self._github.with_auth(
258-
self._github.auth.as_oauth_app().as_web_user(code, redirect_uri)
266+
self._ctx_github.set(
267+
g := self._github.with_auth(
268+
self._github.auth.as_oauth_app().as_web_user(code, redirect_uri)
269+
)
259270
)
260-
async with self._ctx_github:
261-
try:
271+
try:
272+
async with g:
262273
yield self
263-
finally:
264-
self._ctx_github = None
274+
finally:
275+
self._ctx_github.set(None)
265276

266277
@asynccontextmanager
267278
async def as_user(self, token: str) -> AsyncGenerator[Self, None]:
268-
if self._ctx_github is not None:
279+
if self._ctx_github.get() is not None:
269280
raise RuntimeError("Can not enter context twice.")
270-
self._ctx_github = self._github.with_auth(TokenAuthStrategy(token))
271-
async with self._ctx_github:
272-
try:
281+
self._ctx_github.set(g := self._github.with_auth(TokenAuthStrategy(token)))
282+
try:
283+
async with g:
273284
yield self
274-
finally:
275-
self._ctx_github = None
285+
finally:
286+
self._ctx_github.set(None)
276287

277288
@overrides(Bot)
278289
async def handle_event(self, event: Event) -> None:

poetry.lock

Lines changed: 31 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)