hikari-arc 1.2.0__py3-none-any.whl → 1.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
arc/__init__.py CHANGED
@@ -9,6 +9,7 @@ https://arc.hypergonial.com
9
9
  """
10
10
 
11
11
  from alluka import Client as Injector
12
+ from alluka import OverridingContext as InjectorOverridingContext
12
13
  from alluka import inject
13
14
 
14
15
  from arc import abc, command, ext, utils
@@ -28,8 +29,11 @@ from .command import (
28
29
  AttachmentParams,
29
30
  BoolParams,
30
31
  ChannelParams,
32
+ ColorParams,
33
+ ColourParams,
31
34
  FloatParams,
32
35
  IntParams,
36
+ MemberParams,
33
37
  MentionableParams,
34
38
  MessageCommand,
35
39
  RoleParams,
@@ -49,6 +53,7 @@ from .context import AutocompleteData, AutodeferMode, Context, InteractionRespon
49
53
  from .errors import (
50
54
  ArcError,
51
55
  AutocompleteError,
56
+ BotMissingPermissionsError,
52
57
  CommandInvokeError,
53
58
  CommandPublishFailedError,
54
59
  DMOnlyError,
@@ -64,6 +69,7 @@ from .errors import (
64
69
  MaxConcurrencyReachedError,
65
70
  NoResponseIssuedError,
66
71
  NotOwnerError,
72
+ OptionConverterFailureError,
67
73
  ResponseAlreadyIssuedError,
68
74
  UnderCooldownError,
69
75
  )
@@ -112,7 +118,7 @@ __all__ = (
112
118
  "AutocompleteData",
113
119
  "Option",
114
120
  "Context",
115
- "Context",
121
+ "InjectorOverridingContext",
116
122
  "BoolParams",
117
123
  "IntParams",
118
124
  "StrParams",
@@ -122,6 +128,9 @@ __all__ = (
122
128
  "RoleParams",
123
129
  "MentionableParams",
124
130
  "AttachmentParams",
131
+ "MemberParams",
132
+ "ColorParams",
133
+ "ColourParams",
125
134
  "SlashCommand",
126
135
  "SlashGroup",
127
136
  "SlashSubCommand",
@@ -148,6 +157,7 @@ __all__ = (
148
157
  "CommandPublishFailedError",
149
158
  "GuildCommandPublishFailedError",
150
159
  "GlobalCommandPublishFailedError",
160
+ "BotMissingPermissionsError",
151
161
  "MaxConcurrencyReachedError",
152
162
  "NoResponseIssuedError",
153
163
  "ResponseAlreadyIssuedError",
@@ -156,6 +166,7 @@ __all__ = (
156
166
  "ExtensionUnloadError",
157
167
  "HookAbortError",
158
168
  "InteractionResponseError",
169
+ "OptionConverterFailureError",
159
170
  "PluginBase",
160
171
  "RESTPluginBase",
161
172
  "GatewayPluginBase",
arc/__main__.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """CLI entry point for arc."""
2
+
2
3
  import os
3
4
  import platform
4
5
  import sys
arc/abc/__init__.py CHANGED
@@ -8,6 +8,7 @@ from .hookable import Hookable, HookResult, with_hook, with_post_hook
8
8
  from .limiter import LimiterProto
9
9
  from .option import (
10
10
  CommandOptionBase,
11
+ ConverterOption,
11
12
  Option,
12
13
  OptionBase,
13
14
  OptionParams,
@@ -29,6 +30,7 @@ __all__ = (
29
30
  "OptionBase",
30
31
  "OptionType",
31
32
  "CommandOptionBase",
33
+ "ConverterOption",
32
34
  "OptionParams",
33
35
  "OptionWithChoices",
34
36
  "OptionWithChoicesParams",
arc/abc/client.py CHANGED
@@ -15,13 +15,14 @@ from contextlib import suppress
15
15
  import alluka
16
16
  import hikari
17
17
 
18
- from arc.abc.command import _CommandSettings
18
+ from arc.abc.command import CallableCommandBase, _CommandSettings
19
19
  from arc.abc.plugin import PluginBase
20
20
  from arc.command.message import MessageCommand
21
21
  from arc.command.slash import SlashCommand, SlashGroup, SlashSubCommand, SlashSubGroup
22
22
  from arc.command.user import UserCommand
23
23
  from arc.context import AutodeferMode, Context
24
24
  from arc.errors import ExtensionLoadError, ExtensionUnloadError
25
+ from arc.internal.deprecation import warn_deprecate
25
26
  from arc.internal.sync import _sync_commands
26
27
  from arc.internal.types import (
27
28
  AppT,
@@ -30,11 +31,13 @@ from arc.internal.types import (
30
31
  CustomLocaleRequestT,
31
32
  ErrorHandlerCallbackT,
32
33
  HookT,
34
+ InjectionHookT,
33
35
  LifeCycleHookT,
34
36
  OptionLocaleRequestT,
35
37
  PostHookT,
36
38
  ResponseBuilderT,
37
39
  )
40
+ from arc.internal.version import Version
38
41
  from arc.locale import CommandLocaleRequest, LocaleResponse, OptionLocaleRequest
39
42
 
40
43
  if t.TYPE_CHECKING:
@@ -98,10 +101,11 @@ class Client(t.Generic[AppT], abc.ABC):
98
101
  "_loaded_extensions",
99
102
  "_hooks",
100
103
  "_post_hooks",
104
+ "_injection_hooks",
101
105
  "_owner_ids",
102
106
  "_error_handler",
103
- "_startup_hook",
104
- "_shutdown_hook",
107
+ "_startup_hooks",
108
+ "_shutdown_hooks",
105
109
  "_provided_locales",
106
110
  "_command_locale_provider",
107
111
  "_option_locale_provider",
@@ -149,14 +153,15 @@ class Client(t.Generic[AppT], abc.ABC):
149
153
  self._loaded_extensions: list[str] = []
150
154
  self._hooks: list[HookT[te.Self]] = []
151
155
  self._post_hooks: list[PostHookT[te.Self]] = []
156
+ self._injection_hooks: list[InjectionHookT[te.Self]] = []
152
157
  self._owner_ids: list[hikari.Snowflake] = []
153
158
  self._tasks: set[asyncio.Task[t.Any]] = set()
154
159
  self._started: asyncio.Event = asyncio.Event()
155
160
  self._application: hikari.Application | None = None
156
161
  self._error_handler: ErrorHandlerCallbackT[te.Self] | None = None
157
162
  self._concurrency_limiter: ConcurrencyLimiterProto[te.Self] | None = None
158
- self._startup_hook: LifeCycleHookT[te.Self] | None = None
159
- self._shutdown_hook: LifeCycleHookT[te.Self] | None = None
163
+ self._startup_hooks: list[LifeCycleHookT[te.Self] | None] = [None]
164
+ self._shutdown_hooks: list[LifeCycleHookT[te.Self] | None] = [None]
160
165
  self._command_locale_provider: CommandLocaleRequestT | None = None
161
166
  self._option_locale_provider: OptionLocaleRequestT | None = None
162
167
  self._custom_locale_provider: CustomLocaleRequestT | None = None
@@ -285,8 +290,13 @@ class Client(t.Generic[AppT], abc.ABC):
285
290
  await _sync_commands(self)
286
291
 
287
292
  try:
288
- if self._startup_hook:
289
- await self._startup_hook(self)
293
+ for hook in self._startup_hooks:
294
+ if hook:
295
+ try:
296
+ await hook(self)
297
+ except Exception as e:
298
+ logger.error(f"Error in startup hook '{hook.__name__}': {e}")
299
+ traceback.print_exc()
290
300
  finally:
291
301
  self._started.set()
292
302
 
@@ -294,8 +304,16 @@ class Client(t.Generic[AppT], abc.ABC):
294
304
  """Called when the client is shutting down.
295
305
  Reserved for internal shutdown logic.
296
306
  """
297
- if self._shutdown_hook:
298
- await self._shutdown_hook(self)
307
+ for hook in self._shutdown_hooks:
308
+ if hook:
309
+ try:
310
+ await hook(self)
311
+ except Exception as e:
312
+ logger.error(f"Error in shutdown hook '{hook.__name__}': {e}")
313
+ traceback.print_exc()
314
+
315
+ for task in self._tasks:
316
+ task.cancel()
299
317
 
300
318
  async def _on_error(self, ctx: Context[te.Self], exception: Exception) -> None:
301
319
  if self._error_handler is not None:
@@ -311,6 +329,16 @@ class Client(t.Generic[AppT], abc.ABC):
311
329
  if ctx.is_valid:
312
330
  await ctx.respond("❌ Something went wrong. Please contact the bot developer.")
313
331
 
332
+ async def _create_overriding_ctx_for_command(self, ctx: Context[te.Self]) -> alluka.OverridingContext:
333
+ inj_ctx = alluka.OverridingContext.from_client(self.injector)
334
+
335
+ for hook in self._injection_hooks:
336
+ if inspect.iscoroutinefunction(hook):
337
+ await hook(ctx, inj_ctx)
338
+ else:
339
+ hook(ctx, inj_ctx)
340
+ return inj_ctx
341
+
314
342
  def _provide_command_locale(self, request: CommandLocaleRequest) -> LocaleResponse:
315
343
  """Provide a locale for a command."""
316
344
  if self._command_locale_provider is None:
@@ -417,26 +445,24 @@ class Client(t.Generic[AppT], abc.ABC):
417
445
  @t.overload
418
446
  def walk_commands(
419
447
  self, command_type: t.Literal[hikari.CommandType.USER], *, callable_only: bool = False
420
- ) -> t.Iterator[UserCommand[te.Self]]:
421
- ...
448
+ ) -> t.Iterator[UserCommand[te.Self]]: ...
422
449
 
423
450
  @t.overload
424
451
  def walk_commands(
425
452
  self, command_type: t.Literal[hikari.CommandType.MESSAGE], *, callable_only: bool = False
426
- ) -> t.Iterator[MessageCommand[te.Self]]:
427
- ...
453
+ ) -> t.Iterator[MessageCommand[te.Self]]: ...
428
454
 
429
455
  @t.overload
430
456
  def walk_commands(
431
457
  self, command_type: t.Literal[hikari.CommandType.SLASH], *, callable_only: t.Literal[False] = False
432
- ) -> t.Iterator[SlashCommand[te.Self] | SlashSubCommand[te.Self] | SlashGroup[te.Self] | SlashSubGroup[te.Self]]:
433
- ...
458
+ ) -> t.Iterator[
459
+ SlashCommand[te.Self] | SlashSubCommand[te.Self] | SlashGroup[te.Self] | SlashSubGroup[te.Self]
460
+ ]: ...
434
461
 
435
462
  @t.overload
436
463
  def walk_commands(
437
464
  self, command_type: t.Literal[hikari.CommandType.SLASH], *, callable_only: t.Literal[True] = True
438
- ) -> t.Iterator[SlashCommand[te.Self] | SlashSubCommand[te.Self]]:
439
- ...
465
+ ) -> t.Iterator[SlashCommand[te.Self] | SlashSubCommand[te.Self]]: ...
440
466
 
441
467
  def walk_commands( # noqa: C901
442
468
  self, command_type: hikari.CommandType, *, callable_only: bool = False
@@ -507,16 +533,19 @@ class Client(t.Generic[AppT], abc.ABC):
507
533
  yield command
508
534
 
509
535
  @t.overload
510
- def include(self) -> t.Callable[[CommandBase[te.Self, BuilderT]], CommandBase[te.Self, BuilderT]]:
511
- ...
536
+ def include(
537
+ self,
538
+ ) -> t.Callable[[CallableCommandBase[te.Self, BuilderT]], CallableCommandBase[te.Self, BuilderT]]: ...
512
539
 
513
540
  @t.overload
514
- def include(self, command: CommandBase[te.Self, BuilderT]) -> CommandBase[te.Self, BuilderT]:
515
- ...
541
+ def include(self, command: CallableCommandBase[te.Self, BuilderT]) -> CallableCommandBase[te.Self, BuilderT]: ...
516
542
 
517
543
  def include(
518
- self, command: CommandBase[te.Self, BuilderT] | None = None
519
- ) -> CommandBase[te.Self, BuilderT] | t.Callable[[CommandBase[te.Self, BuilderT]], CommandBase[te.Self, BuilderT]]:
544
+ self, command: CallableCommandBase[te.Self, BuilderT] | None = None
545
+ ) -> (
546
+ CallableCommandBase[te.Self, BuilderT]
547
+ | t.Callable[[CallableCommandBase[te.Self, BuilderT]], CallableCommandBase[te.Self, BuilderT]]
548
+ ):
520
549
  """Decorator to add a command to this client.
521
550
 
522
551
  !!! note
@@ -542,7 +571,7 @@ class Client(t.Generic[AppT], abc.ABC):
542
571
  ```
543
572
  """
544
573
 
545
- def decorator(command: CommandBase[te.Self, BuilderT]) -> CommandBase[te.Self, BuilderT]:
574
+ def decorator(command: CallableCommandBase[te.Self, BuilderT]) -> CallableCommandBase[te.Self, BuilderT]:
546
575
  if command.plugin is not None:
547
576
  raise RuntimeError(
548
577
  f"Command '{command.name}' is already registered with plugin '{command.plugin.name}'."
@@ -700,12 +729,10 @@ class Client(t.Generic[AppT], abc.ABC):
700
729
  return self
701
730
 
702
731
  @t.overload
703
- def add_hook(self, hook: HookT[te.Self]) -> te.Self:
704
- ...
732
+ def add_hook(self, hook: HookT[te.Self]) -> te.Self: ...
705
733
 
706
734
  @t.overload
707
- def add_hook(self) -> t.Callable[[HookT[te.Self]], HookT[te.Self]]:
708
- ...
735
+ def add_hook(self) -> t.Callable[[HookT[te.Self]], HookT[te.Self]]: ...
709
736
 
710
737
  def add_hook(self, hook: HookT[te.Self] | None = None) -> te.Self | t.Callable[[HookT[te.Self]], HookT[te.Self]]:
711
738
  """Add a pre-execution hook to this client.
@@ -736,12 +763,10 @@ class Client(t.Generic[AppT], abc.ABC):
736
763
  return decorator
737
764
 
738
765
  @t.overload
739
- def add_post_hook(self, hook: PostHookT[te.Self]) -> te.Self:
740
- ...
766
+ def add_post_hook(self, hook: PostHookT[te.Self]) -> te.Self: ...
741
767
 
742
768
  @t.overload
743
- def add_post_hook(self) -> t.Callable[[PostHookT[te.Self]], PostHookT[te.Self]]:
744
- ...
769
+ def add_post_hook(self) -> t.Callable[[PostHookT[te.Self]], PostHookT[te.Self]]: ...
745
770
 
746
771
  def add_post_hook(
747
772
  self, hook: PostHookT[te.Self] | None = None
@@ -777,12 +802,76 @@ class Client(t.Generic[AppT], abc.ABC):
777
802
  return decorator
778
803
 
779
804
  @t.overload
780
- def set_error_handler(self, handler: ErrorHandlerCallbackT[te.Self]) -> te.Self:
781
- ...
805
+ def add_injection_hook(self, hook: InjectionHookT[te.Self]) -> te.Self: ...
782
806
 
783
807
  @t.overload
784
- def set_error_handler(self) -> t.Callable[[ErrorHandlerCallbackT[te.Self]], te.Self]:
785
- ...
808
+ def add_injection_hook(self) -> t.Callable[[InjectionHookT[te.Self]], InjectionHookT[te.Self]]: ...
809
+
810
+ def add_injection_hook(
811
+ self, hook: InjectionHookT[te.Self] | None = None
812
+ ) -> te.Self | t.Callable[[InjectionHookT[te.Self]], InjectionHookT[te.Self]]:
813
+ """Add an injection hook to this client.
814
+ This hook will be called when a command is called, and an OverridingContext is passed, allowing you to inject dependencies for the command call.
815
+
816
+ Parameters
817
+ ----------
818
+ hook : InjectionHookT[te.Self]
819
+ The hook to add.
820
+
821
+ Returns
822
+ -------
823
+ te.Self
824
+ The client for chaining calls.
825
+
826
+ Example
827
+ -------
828
+ ```py
829
+ @client.add_injection_hook
830
+ async def inject(ctx: arc.GatewayContext, inj_ctx: arc.InjectorOverridingContext) -> None:
831
+ foo: MyType = example_data[ctx.guild_id]
832
+ inj_ctx.set_type_dependency(MyType, foo)
833
+ ```
834
+
835
+ See Also
836
+ --------
837
+ - [`Client.set_type_dependency`][arc.client.Client.set_type_dependency]
838
+ """
839
+ if hook is not None:
840
+ self._injection_hooks.append(hook)
841
+ return self
842
+
843
+ def decorator(hook: InjectionHookT[te.Self]) -> InjectionHookT[te.Self]:
844
+ self._injection_hooks.append(hook)
845
+ return hook
846
+
847
+ return decorator
848
+
849
+ def remove_injection_hook(self, hook: InjectionHookT[te.Self]) -> te.Self:
850
+ """Remove an injection hook from this client.
851
+
852
+ Parameters
853
+ ----------
854
+ hook : InjectionHookT[te.Self]
855
+ The hook to remove.
856
+
857
+ Returns
858
+ -------
859
+ te.Self
860
+ The client for chaining calls.
861
+
862
+ Raises
863
+ ------
864
+ ValueError
865
+ If the hook is not registered with this client.
866
+ """
867
+ self._injection_hooks.remove(hook)
868
+ return self
869
+
870
+ @t.overload
871
+ def set_error_handler(self, handler: ErrorHandlerCallbackT[te.Self]) -> te.Self: ...
872
+
873
+ @t.overload
874
+ def set_error_handler(self) -> t.Callable[[ErrorHandlerCallbackT[te.Self]], te.Self]: ...
786
875
 
787
876
  def set_error_handler(
788
877
  self, handler: ErrorHandlerCallbackT[te.Self] | None = None
@@ -831,12 +920,104 @@ class Client(t.Generic[AppT], abc.ABC):
831
920
  return decorator
832
921
 
833
922
  @t.overload
834
- def set_startup_hook(self, hook: LifeCycleHookT[te.Self]) -> te.Self:
835
- ...
923
+ def add_startup_hook(self, hook: LifeCycleHookT[te.Self]) -> te.Self: ...
924
+
925
+ @t.overload
926
+ def add_startup_hook(self) -> t.Callable[[LifeCycleHookT[te.Self]], te.Self]: ...
927
+
928
+ def add_startup_hook(
929
+ self, hook: LifeCycleHookT[te.Self] | None = None
930
+ ) -> te.Self | t.Callable[[LifeCycleHookT[te.Self]], te.Self]:
931
+ """Decorator to add a startup hook for this client.
932
+
933
+ This will be called when the client starts up.
934
+
935
+ Parameters
936
+ ----------
937
+ hook : LifeCycleHookT[te.Self]
938
+ The startup hook to add.
939
+
940
+ Returns
941
+ -------
942
+ te.Self
943
+ The client for chaining calls.
944
+
945
+ Examples
946
+ --------
947
+ ```py
948
+ @client.add_startup_hook
949
+ async def startup_hook(client: arc.GatewayClient) -> None:
950
+ print("Client started up!")
951
+ ```
952
+
953
+ Or, as a function:
954
+
955
+ ```py
956
+ client.add_startup_hook(startup_hook)
957
+ ```
958
+ """
959
+
960
+ def decorator(handler: LifeCycleHookT[te.Self]) -> te.Self:
961
+ self._startup_hooks.append(handler)
962
+ return self
963
+
964
+ if hook is not None:
965
+ return decorator(hook)
966
+
967
+ return decorator
968
+
969
+ @t.overload
970
+ def add_shutdown_hook(self, hook: LifeCycleHookT[te.Self]) -> te.Self: ...
836
971
 
837
972
  @t.overload
838
- def set_startup_hook(self) -> t.Callable[[LifeCycleHookT[te.Self]], te.Self]:
839
- ...
973
+ def add_shutdown_hook(self) -> t.Callable[[LifeCycleHookT[te.Self]], te.Self]: ...
974
+
975
+ def add_shutdown_hook(
976
+ self, hook: LifeCycleHookT[te.Self] | None = None
977
+ ) -> te.Self | t.Callable[[LifeCycleHookT[te.Self]], te.Self]:
978
+ """Decorator to add a shutdown hook for this client.
979
+
980
+ This will be called when the client shuts down.
981
+
982
+ Parameters
983
+ ----------
984
+ hook : LifeCycleHookT[te.Self]
985
+ The shutdown hook to add.
986
+
987
+ Returns
988
+ -------
989
+ te.Self
990
+ The client for chaining calls.
991
+
992
+ Examples
993
+ --------
994
+ ```py
995
+ @client.add_shutdown_hook
996
+ async def shutdown_hook(client: arc.GatewayClient) -> None:
997
+ print("Client shut down!")
998
+ ```
999
+
1000
+ Or, as a function:
1001
+
1002
+ ```py
1003
+ client.add_shutdown_hook(shutdown_hook)
1004
+ ```
1005
+ """
1006
+
1007
+ def decorator(handler: LifeCycleHookT[te.Self]) -> te.Self:
1008
+ self._shutdown_hooks.append(handler)
1009
+ return self
1010
+
1011
+ if hook is not None:
1012
+ return decorator(hook)
1013
+
1014
+ return decorator
1015
+
1016
+ @t.overload
1017
+ def set_startup_hook(self, hook: LifeCycleHookT[te.Self]) -> te.Self: ...
1018
+
1019
+ @t.overload
1020
+ def set_startup_hook(self) -> t.Callable[[LifeCycleHookT[te.Self]], te.Self]: ...
840
1021
 
841
1022
  def set_startup_hook(
842
1023
  self, hook: LifeCycleHookT[te.Self] | None = None
@@ -845,6 +1026,10 @@ class Client(t.Generic[AppT], abc.ABC):
845
1026
 
846
1027
  This will be called when the client starts up.
847
1028
 
1029
+ !!! warning "Deprecation Notice"
1030
+ This method is deprecated and will be removed in version `2.0.0`.
1031
+ Use [`Client.add_startup_hook`][arc.client.Client.add_startup_hook] instead.
1032
+
848
1033
  Parameters
849
1034
  ----------
850
1035
  hook : LifeCycleHookT[te.Self]
@@ -869,9 +1054,10 @@ class Client(t.Generic[AppT], abc.ABC):
869
1054
  client.set_startup_hook(startup_hook)
870
1055
  ```
871
1056
  """
1057
+ warn_deprecate(what="set_startup_hook", when=Version(2, 0, 0), use_instead="add_startup_hook")
872
1058
 
873
1059
  def decorator(handler: LifeCycleHookT[te.Self]) -> te.Self:
874
- self._startup_hook = handler
1060
+ self._startup_hooks[0] = handler
875
1061
  return self
876
1062
 
877
1063
  if hook is not None:
@@ -880,12 +1066,10 @@ class Client(t.Generic[AppT], abc.ABC):
880
1066
  return decorator
881
1067
 
882
1068
  @t.overload
883
- def set_shutdown_hook(self, hook: LifeCycleHookT[te.Self]) -> te.Self:
884
- ...
1069
+ def set_shutdown_hook(self, hook: LifeCycleHookT[te.Self]) -> te.Self: ...
885
1070
 
886
1071
  @t.overload
887
- def set_shutdown_hook(self) -> t.Callable[[LifeCycleHookT[te.Self]], te.Self]:
888
- ...
1072
+ def set_shutdown_hook(self) -> t.Callable[[LifeCycleHookT[te.Self]], te.Self]: ...
889
1073
 
890
1074
  def set_shutdown_hook(
891
1075
  self, hook: LifeCycleHookT[te.Self] | None = None
@@ -894,6 +1078,10 @@ class Client(t.Generic[AppT], abc.ABC):
894
1078
 
895
1079
  This will be called when the client shuts down.
896
1080
 
1081
+ !!! warning "Deprecation Notice"
1082
+ This method is deprecated and will be removed in version `2.0.0`.
1083
+ Use [`Client.add_shutdown_hook`][arc.client.Client.add_shutdown_hook] instead.
1084
+
897
1085
  Parameters
898
1086
  ----------
899
1087
  hook : LifeCycleHookT[te.Self]
@@ -918,9 +1106,10 @@ class Client(t.Generic[AppT], abc.ABC):
918
1106
  client.set_shutdown_hook(shutdown_hook)
919
1107
  ```
920
1108
  """
1109
+ warn_deprecate(what="set_shutdown_hook", when=Version(2, 0, 0), use_instead="add_shutdown_hook")
921
1110
 
922
1111
  def decorator(handler: LifeCycleHookT[te.Self]) -> te.Self:
923
- self._shutdown_hook = handler
1112
+ self._shutdown_hooks[0] = handler
924
1113
  return self
925
1114
 
926
1115
  if hook is not None:
@@ -929,12 +1118,10 @@ class Client(t.Generic[AppT], abc.ABC):
929
1118
  return decorator
930
1119
 
931
1120
  @t.overload
932
- def set_command_locale_provider(self, provider: CommandLocaleRequestT) -> te.Self:
933
- ...
1121
+ def set_command_locale_provider(self, provider: CommandLocaleRequestT) -> te.Self: ...
934
1122
 
935
1123
  @t.overload
936
- def set_command_locale_provider(self) -> t.Callable[[CommandLocaleRequestT], te.Self]:
937
- ...
1124
+ def set_command_locale_provider(self) -> t.Callable[[CommandLocaleRequestT], te.Self]: ...
938
1125
 
939
1126
  def set_command_locale_provider(
940
1127
  self, provider: CommandLocaleRequestT | None = None
@@ -978,12 +1165,10 @@ class Client(t.Generic[AppT], abc.ABC):
978
1165
  return decorator
979
1166
 
980
1167
  @t.overload
981
- def set_option_locale_provider(self, provider: OptionLocaleRequestT) -> te.Self:
982
- ...
1168
+ def set_option_locale_provider(self, provider: OptionLocaleRequestT) -> te.Self: ...
983
1169
 
984
1170
  @t.overload
985
- def set_option_locale_provider(self) -> t.Callable[[OptionLocaleRequestT], te.Self]:
986
- ...
1171
+ def set_option_locale_provider(self) -> t.Callable[[OptionLocaleRequestT], te.Self]: ...
987
1172
 
988
1173
  def set_option_locale_provider(
989
1174
  self, provider: OptionLocaleRequestT | None = None
@@ -1027,12 +1212,10 @@ class Client(t.Generic[AppT], abc.ABC):
1027
1212
  return decorator
1028
1213
 
1029
1214
  @t.overload
1030
- def set_custom_locale_provider(self, provider: CustomLocaleRequestT) -> te.Self:
1031
- ...
1215
+ def set_custom_locale_provider(self, provider: CustomLocaleRequestT) -> te.Self: ...
1032
1216
 
1033
1217
  @t.overload
1034
- def set_custom_locale_provider(self) -> t.Callable[[CustomLocaleRequestT], te.Self]:
1035
- ...
1218
+ def set_custom_locale_provider(self) -> t.Callable[[CustomLocaleRequestT], te.Self]: ...
1036
1219
 
1037
1220
  def set_custom_locale_provider(
1038
1221
  self, provider: CustomLocaleRequestT | None = None
@@ -1282,12 +1465,10 @@ class Client(t.Generic[AppT], abc.ABC):
1282
1465
  return self
1283
1466
 
1284
1467
  @t.overload
1285
- def get_type_dependency(self, type_: type[T]) -> T:
1286
- ...
1468
+ def get_type_dependency(self, type_: type[T]) -> T: ...
1287
1469
 
1288
1470
  @t.overload
1289
- def get_type_dependency(self, type_: type[T], *, default: DefaultT) -> T | DefaultT:
1290
- ...
1471
+ def get_type_dependency(self, type_: type[T], *, default: DefaultT) -> T | DefaultT: ...
1291
1472
 
1292
1473
  def get_type_dependency(
1293
1474
  self, type_: type[T], *, default: DefaultT | hikari.UndefinedType = hikari.UNDEFINED
@@ -1313,20 +1494,15 @@ class Client(t.Generic[AppT], abc.ABC):
1313
1494
  If the dependency does not exist and `default` was not provided.
1314
1495
  """
1315
1496
  if default is hikari.UNDEFINED:
1316
- value = self._injector.get_type_dependency(type_)
1317
- if isinstance(value, alluka.abc.Undefined):
1318
- raise KeyError(f"Could not resolve dependency of type {type_}.")
1319
- return value
1497
+ return self._injector.get_type_dependency(type_)
1320
1498
  else:
1321
1499
  return self._injector.get_type_dependency(type_, default=default)
1322
1500
 
1323
1501
  @t.overload
1324
- def inject_dependencies(self, func: t.Callable[P, T]) -> t.Callable[P, T]:
1325
- ...
1502
+ def inject_dependencies(self, func: t.Callable[P, T]) -> t.Callable[P, T]: ...
1326
1503
 
1327
1504
  @t.overload
1328
- def inject_dependencies(self) -> t.Callable[[t.Callable[P, T]], t.Callable[P, T]]:
1329
- ...
1505
+ def inject_dependencies(self) -> t.Callable[[t.Callable[P, T]], t.Callable[P, T]]: ...
1330
1506
 
1331
1507
  def inject_dependencies(
1332
1508
  self, func: t.Callable[P, T] | None = None