Skip to content

Commit

Permalink
Change dump_tokens to save_tokens; add override to Client.close()
Browse files Browse the repository at this point in the history
  • Loading branch information
EvieePy committed Dec 23, 2024
1 parent 0493b7f commit cc61f6f
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 27 deletions.
2 changes: 1 addition & 1 deletion twitchio/authentication/tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ async def close(self) -> None:
await super().close()
await self.__isolated.close()

async def dump(self, name: str | None = None) -> None:
async def save(self, name: str | None = None) -> None:
if not self._has_loaded:
return

Expand Down
59 changes: 35 additions & 24 deletions twitchio/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def __init__(

self._login_called: bool = False
self._has_closed: bool = False
self._dump_tokens: bool = True
self._save_tokens: bool = True

# Websockets for EventSub
self._websockets: dict[str, dict[str, Websocket]] = defaultdict(dict)
Expand All @@ -169,7 +169,7 @@ def tokens(self) -> MappingProxyType[str, TokenMappingData]:
:meth:`~.load_tokens`
:meth:`~.dump_tokens`
:meth:`~.save_tokens`
:meth:`~.add_token`
Expand Down Expand Up @@ -257,7 +257,7 @@ async def setup_hook(self) -> None:
"""
...

async def login(self, *, token: str | None = None, load_tokens: bool = True, dump_tokens: bool = True) -> None:
async def login(self, *, token: str | None = None, load_tokens: bool = True, save_tokens: bool = True) -> None:
"""Method to login the client and generate or store an app token.
This method is called automatically when using :meth:`~.start`.
Expand All @@ -277,15 +277,15 @@ async def login(self, *, token: str | None = None, load_tokens: bool = True, dum
load_tokens: bool
Optional bool which indicates whether the :class:`Client` should call :meth:`.load_tokens` during
login automatically. Defaults to ``True``.
dump_tokens: bool
Optional bool which inicates whether the :class:`Client` should call :meth:`.dump_tokens` during the
save_tokens: bool
Optional bool which inicates whether the :class:`Client` should call :meth:`.save_tokens` during the
:meth:`.close` automatically. Defaults to ``True``.
"""
if self._login_called:
return

self._login_called = True
self._dump_tokens = dump_tokens
self._save_tokens = save_tokens

if not token:
payload: ClientCredentialsPayload = await self._http.client_credentials_token()
Expand Down Expand Up @@ -314,7 +314,7 @@ async def start(
*,
with_adapter: bool = True,
load_tokens: bool = True,
dump_tokens: bool = True,
save_tokens: bool = True,
) -> None:
"""|coro|
Expand All @@ -336,8 +336,8 @@ async def start(
load_tokens: bool
Optional bool which indicates whether the :class:`Client` should call :meth:`.load_tokens` during
:meth:`.login` automatically. Defaults to ``True``.
dump_tokens: bool
Optional bool which inicates whether the :class:`Client` should call :meth:`.dump_tokens` during the
save_tokens: bool
Optional bool which inicates whether the :class:`Client` should call :meth:`.save_tokens` during the
:meth:`.close` automatically. Defaults to ``True``.
Examples
Expand All @@ -356,7 +356,7 @@ async def main() -> None:
await client.start()
"""
self.__waiter.clear()
await self.login(token=token, load_tokens=load_tokens, dump_tokens=dump_tokens)
await self.login(token=token, load_tokens=load_tokens, save_tokens=save_tokens)

if with_adapter:
await self._adapter.run()
Expand All @@ -377,7 +377,7 @@ def run(
*,
with_adapter: bool = True,
load_tokens: bool = True,
dump_tokens: bool = True,
save_tokens: bool = True,
) -> None:
"""Method to login the client and create a continuously running event loop.
Expand Down Expand Up @@ -405,8 +405,8 @@ def run(
load_tokens: bool
Optional bool which indicates whether the :class:`Client` should call :meth:`.load_tokens` during
:meth:`.login` automatically. Defaults to ``True``.
dump_tokens: bool
Optional bool which inicates whether the :class:`Client` should call :meth:`.dump_tokens` during the
save_tokens: bool
Optional bool which inicates whether the :class:`Client` should call :meth:`.save_tokens` during the
:meth:`.close` automatically. Defaults to ``True``.
Examples
Expand All @@ -420,22 +420,30 @@ def run(

async def run() -> None:
async with self:
await self.start(token=token, with_adapter=with_adapter, load_tokens=load_tokens, dump_tokens=dump_tokens)
await self.start(token=token, with_adapter=with_adapter, load_tokens=load_tokens, save_tokens=save_tokens)

try:
asyncio.run(run())
except KeyboardInterrupt:
pass

async def close(self) -> None:
"""Method which closes the :class:`~Client` gracefully.
async def close(self, **options: Any) -> None:
r"""Method which closes the :class:`~Client` gracefully.
This method is called for you automatically when using :meth:`~.run` or when using the client with the
async context-manager, E.g: `async with client:`
You can override this method to implement your own clean-up logic, however you should call `await super().close()`
when doing this.
Parameters
----------
\*
save_tokens: bool | None
An optional bool override which allows overriding the identical keyword-argument set in either
:meth:`.run`, :meth:`.start` or :meth:`.login` to call the :meth:`.save_tokens` coroutine.
Defaults to ``None`` which won't override.
Examples
--------
Expand All @@ -462,9 +470,12 @@ async def close(self) -> None:
for socket in sockets:
await socket.close()

if self._dump_tokens:
save_tokens = options.get("save_tokens")
save = save_tokens if save_tokens is not None else self._save_tokens

if save:
async with self._http._token_lock:
await self.dump_tokens()
await self.save_tokens()

self._http.cleanup()
self.__waiter.set()
Expand Down Expand Up @@ -627,7 +638,7 @@ async def load_tokens(self, path: str | None = None, /) -> None:
You can override this method to implement your own token loading logic into the client, such as from a database.
By default this method loads tokens from a file named `".tio.tokens.json"` if it is present;
always present if you use the default method of dumping tokens.
always present if you use the default method of saving tokens.
**However**, it is preferred you would override this function to load your tokens from a database,
as this has far less chance of being corrupted, damaged or lost.
Expand Down Expand Up @@ -655,19 +666,19 @@ async def load_tokens(self, path: str | None = None) -> None:
"""
await self._http.load_tokens(name=path)

async def dump_tokens(self, path: str | None = None, /) -> None:
async def save_tokens(self, path: str | None = None, /) -> None:
"""|coro|
Method which dumps all the added OAuth tokens currently managed by this Client.
Method which saves all the added OAuth tokens currently managed by this Client.
.. note::
This method is called by the client when it is gracefully closed and the ``dump_tokens`` keyword-argument
This method is called by the client when it is gracefully closed and the ``save_tokens`` keyword-argument
is ``True`` in either, :meth:`.run`, :meth:`.start` or :meth:`.login` (Default).
.. note::
By default this method dumps to a JSON file named `".tio.tokens.json"`.
By default this method saves to a JSON file named `".tio.tokens.json"`.
You can override this method to implement your own custom logic, such as saving tokens to a database, however
it is preferred to use :meth:`~.add_token` to ensure the tokens are handled as they are added.
Expand All @@ -677,7 +688,7 @@ async def dump_tokens(self, path: str | None = None, /) -> None:
path: str | None
The path of the file to save to. Defaults to `.tio.tokens.json`.
"""
await self._http.dump(path)
await self._http.save(path)

def add_listener(self, listener: Callable[..., Coroutine[Any, Any, None]], *, event: str | None = None) -> None:
# TODO: Docs...
Expand Down
4 changes: 2 additions & 2 deletions twitchio/ext/commands/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ def owner_id(self) -> str | None:
"""
return self._owner_id

async def close(self) -> None:
async def close(self, **options: Any) -> None:
for module in tuple(self.__modules):
try:
await self.unload_module(module)
Expand All @@ -217,7 +217,7 @@ async def close(self) -> None:
except Exception as e:
logger.debug('Failed to remove component "%s" gracefully during close: %s.', component, e)

await super().close()
await super().close(**options)

def _cleanup_component(self, component: Component, /) -> None:
for command in component.__all_commands__.values():
Expand Down

0 comments on commit cc61f6f

Please sign in to comment.