Skip to content

Commit 7fa1547

Browse files
committed
2 parents 8be3577 + 8fc3b11 commit 7fa1547

File tree

4 files changed

+58
-7
lines changed

4 files changed

+58
-7
lines changed

twitchio/client.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,38 @@ def __init__(
165165
self._ready_event.clear()
166166

167167
self.__waiter: asyncio.Event = asyncio.Event()
168+
self._setup_called = False
169+
170+
@property
171+
def adapter(self) -> BaseAdapter:
172+
"""Property returning the :class:`~twitchio.AiohttpAdapter` or :class:`~twitchio.StarlettepAdapter` the bot is
173+
currently running."""
174+
return self._adapter
175+
176+
async def set_adapter(self, adapter: BaseAdapter) -> None:
177+
"""|async|
178+
179+
Method which sets and starts a new web adapter which inherits from either :class:`~twitchio.AiohttpAdapter` or
180+
:class:`~twitchio.StarlettepAdapter` or implements the :class:`~twitchio.BaseAdapter` specifications.
181+
182+
Parameters
183+
----------
184+
adapter: :class:`~twitchio.BaseAdapter`
185+
The new adapter to assign and start.
186+
187+
Returns
188+
-------
189+
None
190+
"""
191+
if self._adapter:
192+
await self._adapter.close(False)
193+
194+
self._adapter = adapter
195+
196+
if self._setup_called:
197+
await self._adapter.run()
198+
199+
self._adapter.client = self
168200

169201
@property
170202
def tokens(self) -> MappingProxyType[str, TokenMappingData]:
@@ -402,6 +434,7 @@ async def login(self, *, token: str | None = None, load_tokens: bool = True, sav
402434
self._user = await partial.user() if self._fetch_self else partial
403435

404436
await self.setup_hook()
437+
self._setup_called = True
405438

406439
async def __aenter__(self) -> Self:
407440
return self
@@ -459,7 +492,7 @@ async def main() -> None:
459492
self.__waiter.clear()
460493
await self.login(token=token, load_tokens=load_tokens, save_tokens=save_tokens)
461494

462-
if with_adapter:
495+
if with_adapter and not self._adapter._running:
463496
await self._adapter.run()
464497

465498
# Dispatch ready event... May change places in the future.

twitchio/web/aio_adapter.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ def __init__(
176176
self.router.add_route("POST", self._eventsub_path, self.eventsub_callback)
177177

178178
self._responded: deque[str] = deque(maxlen=5000)
179+
self._running: bool = False
179180

180181
def __init_subclass__(cls: type[AiohttpAdapter]) -> None:
181182
return
@@ -196,7 +197,7 @@ async def event_startup(self) -> None:
196197
async def event_shutdown(self) -> None:
197198
logger.info("Successfully shutdown TwitchIO <%s>.", self.__class__.__qualname__)
198199

199-
async def close(self) -> None:
200+
async def close(self, *args: Any, **kwargs: Any) -> None:
200201
if self._runner_task is not None:
201202
try:
202203
self._runner_task.cancel()
@@ -212,6 +213,7 @@ async def close(self) -> None:
212213

213214
self._runner = None
214215
self._runner_task = None
216+
self._running = False
215217

216218
def _task_callback(self, task: asyncio.Task[None]) -> None:
217219
if not task.done():
@@ -221,6 +223,8 @@ def _task_callback(self, task: asyncio.Task[None]) -> None:
221223
raise e
222224

223225
async def run(self, host: str | None = None, port: int | None = None) -> None:
226+
self._running = True
227+
224228
self._runner = web.AppRunner(self, access_log=None, handle_signals=True)
225229
await self._runner.setup()
226230

twitchio/web/starlette_adapter.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ def __init__(
174174
on_startup=[self.event_startup],
175175
)
176176
self._closing: bool = False
177+
self._server: uvicorn.Server | None = None
178+
self._running: bool = False
177179

178180
def __repr__(self) -> str:
179181
return f"StarletteAdapter(host={self._host}, port={self._port})"
@@ -194,7 +196,7 @@ async def event_startup(self) -> None:
194196
async def event_shutdown(self) -> None:
195197
await self.close()
196198

197-
async def close(self) -> None:
199+
async def close(self, with_client: bool = True) -> None:
198200
if self._closing:
199201
return
200202

@@ -211,9 +213,16 @@ async def close(self) -> None:
211213
)
212214

213215
self._runner_task = None
214-
await self.client.close()
216+
217+
if with_client:
218+
await self.client.close()
219+
220+
if self._server:
221+
await self._server.shutdown()
215222

216223
logger.info("Successfully shutdown TwitchIO <%s>.", self.__class__.__qualname__)
224+
self._closing = False
225+
self._running = False
217226

218227
def _task_callback(self, task: asyncio.Task[None]) -> None:
219228
if not task.done():
@@ -229,6 +238,8 @@ def _task_callback(self, task: asyncio.Task[None]) -> None:
229238
logger.exception(e.__context__)
230239

231240
async def run(self, host: str | None = None, port: int | None = None) -> None:
241+
self._running = True
242+
232243
self._host = host or self._host
233244
self._port = port or self._port
234245

@@ -241,8 +252,10 @@ async def run(self, host: str | None = None, port: int | None = None) -> None:
241252
timeout_graceful_shutdown=3,
242253
)
243254

244-
server: uvicorn.Server = uvicorn.Server(config)
245-
self._runner_task = asyncio.create_task(server.serve(), name=f"twitchio-web-adapter:{self.__class__.__qualname__}")
255+
self._server = uvicorn.Server(config)
256+
self._runner_task = asyncio.create_task(
257+
self._server.serve(), name=f"twitchio-web-adapter:{self.__class__.__qualname__}"
258+
)
246259
self._runner_task.add_done_callback(self._task_callback)
247260

248261
async def eventsub_callback(self, request: Request) -> Response:

twitchio/web/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class BaseAdapter(abc.ABC):
8686
client: Client
8787
_runner_task: asyncio.Task[None] | None
8888
_eventsub_secret: str | None
89+
_running: bool
8990

9091
@abc.abstractmethod
9192
async def event_startup(self) -> None: ...
@@ -94,7 +95,7 @@ async def event_startup(self) -> None: ...
9495
async def event_shutdown(self) -> None: ...
9596

9697
@abc.abstractmethod
97-
async def close(self) -> None: ...
98+
async def close(self, *args: Any, **kwargs: Any) -> None: ...
9899

99100
@abc.abstractmethod
100101
async def run(self, host: str | None = None, port: int | None = None) -> None: ...

0 commit comments

Comments
 (0)