telegrinder 0.1.dev166__py3-none-any.whl → 0.1.dev168__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.

Potentially problematic release.


This version of telegrinder might be problematic. Click here for more details.

Files changed (64) hide show
  1. telegrinder/__init__.py +0 -2
  2. telegrinder/bot/__init__.py +0 -2
  3. telegrinder/bot/bot.py +1 -3
  4. telegrinder/bot/cute_types/base.py +3 -12
  5. telegrinder/bot/cute_types/callback_query.py +2 -4
  6. telegrinder/bot/cute_types/chat_join_request.py +3 -1
  7. telegrinder/bot/cute_types/chat_member_updated.py +3 -1
  8. telegrinder/bot/cute_types/message.py +10 -31
  9. telegrinder/bot/cute_types/utils.py +1 -3
  10. telegrinder/bot/dispatch/__init__.py +1 -2
  11. telegrinder/bot/dispatch/composition.py +1 -3
  12. telegrinder/bot/dispatch/dispatch.py +5 -6
  13. telegrinder/bot/dispatch/handler/func.py +4 -11
  14. telegrinder/bot/dispatch/return_manager/abc.py +9 -13
  15. telegrinder/bot/dispatch/return_manager/message.py +5 -7
  16. telegrinder/bot/dispatch/view/abc.py +54 -5
  17. telegrinder/bot/dispatch/view/box.py +3 -11
  18. telegrinder/bot/dispatch/view/raw.py +2 -6
  19. telegrinder/bot/dispatch/waiter_machine/__init__.py +1 -2
  20. telegrinder/bot/dispatch/waiter_machine/machine.py +43 -88
  21. telegrinder/bot/dispatch/waiter_machine/middleware.py +12 -5
  22. telegrinder/bot/dispatch/waiter_machine/short_state.py +15 -5
  23. telegrinder/bot/polling/polling.py +2 -6
  24. telegrinder/bot/rules/adapter/event.py +1 -3
  25. telegrinder/bot/rules/callback_data.py +8 -8
  26. telegrinder/bot/rules/fuzzy.py +1 -2
  27. telegrinder/bot/rules/is_from.py +6 -4
  28. telegrinder/bot/rules/markup.py +1 -2
  29. telegrinder/bot/rules/mention.py +1 -4
  30. telegrinder/bot/rules/regex.py +1 -2
  31. telegrinder/bot/rules/rule_enum.py +1 -3
  32. telegrinder/bot/rules/start.py +1 -3
  33. telegrinder/bot/scenario/checkbox.py +6 -10
  34. telegrinder/bot/scenario/choice.py +4 -3
  35. telegrinder/client/aiohttp.py +1 -3
  36. telegrinder/model.py +4 -3
  37. telegrinder/modules.py +1 -3
  38. telegrinder/msgspec_utils.py +1 -3
  39. telegrinder/node/attachment.py +18 -14
  40. telegrinder/node/base.py +4 -11
  41. telegrinder/node/composer.py +1 -3
  42. telegrinder/node/message.py +3 -1
  43. telegrinder/node/source.py +3 -1
  44. telegrinder/node/text.py +3 -1
  45. telegrinder/tools/__init__.py +2 -0
  46. telegrinder/tools/buttons.py +4 -6
  47. telegrinder/tools/error_handler/abc.py +1 -3
  48. telegrinder/tools/error_handler/error.py +3 -6
  49. telegrinder/tools/error_handler/error_handler.py +17 -13
  50. telegrinder/tools/formatting/html.py +2 -6
  51. telegrinder/tools/formatting/links.py +1 -3
  52. telegrinder/tools/global_context/abc.py +1 -3
  53. telegrinder/tools/global_context/global_context.py +13 -31
  54. telegrinder/tools/i18n/middleware/base.py +1 -3
  55. telegrinder/tools/limited_dict.py +37 -0
  56. telegrinder/tools/loop_wrapper/loop_wrapper.py +3 -7
  57. telegrinder/types/__init__.py +30 -0
  58. telegrinder/types/methods.py +20 -89
  59. telegrinder/types/objects.py +16 -45
  60. telegrinder/verification_utils.py +2 -1
  61. {telegrinder-0.1.dev166.dist-info → telegrinder-0.1.dev168.dist-info}/METADATA +5 -5
  62. {telegrinder-0.1.dev166.dist-info → telegrinder-0.1.dev168.dist-info}/RECORD +64 -63
  63. {telegrinder-0.1.dev166.dist-info → telegrinder-0.1.dev168.dist-info}/LICENSE +0 -0
  64. {telegrinder-0.1.dev166.dist-info → telegrinder-0.1.dev168.dist-info}/WHEEL +0 -0
telegrinder/__init__.py CHANGED
@@ -69,7 +69,6 @@ from .bot import (
69
69
  Polling,
70
70
  RawEventView,
71
71
  ShortState,
72
- ShortStateStorage,
73
72
  SingleChoice,
74
73
  Telegrinder,
75
74
  UpdateCute,
@@ -189,7 +188,6 @@ __all__ = (
189
188
  "RawEventView",
190
189
  "RowButtons",
191
190
  "ShortState",
192
- "ShortStateStorage",
193
191
  "SimpleI18n",
194
192
  "SimpleTranslator",
195
193
  "SingleChoice",
@@ -33,7 +33,6 @@ from .dispatch import (
33
33
  MessageView,
34
34
  RawEventView,
35
35
  ShortState,
36
- ShortStateStorage,
37
36
  ViewBox,
38
37
  WaiterMachine,
39
38
  register_manager,
@@ -80,7 +79,6 @@ __all__ = (
80
79
  "Polling",
81
80
  "RawEventView",
82
81
  "ShortState",
83
- "ShortStateStorage",
84
82
  "SingleChoice",
85
83
  "Telegrinder",
86
84
  "UpdateCute",
telegrinder/bot/bot.py CHANGED
@@ -57,9 +57,7 @@ class Telegrinder(typing.Generic[DispatchT, PollingT, LoopWrapperT]):
57
57
 
58
58
  def run_forever(self, *, offset: int = 0, skip_updates: bool = False) -> None:
59
59
  logger.debug("Running blocking polling (id={})", self.api.id)
60
- self.loop_wrapper.add_task(
61
- self.run_polling(offset=offset, skip_updates=skip_updates)
62
- )
60
+ self.loop_wrapper.add_task(self.run_polling(offset=offset, skip_updates=skip_updates))
63
61
  self.loop_wrapper.run_event_loop()
64
62
 
65
63
 
@@ -74,9 +74,7 @@ def compose_method_params(
74
74
  if param_name not in params:
75
75
  if param_name in validators and not validators[param_name](update):
76
76
  continue
77
- params[param_name] = getattr(
78
- update, param if isinstance(param, str) else param[1]
79
- )
77
+ params[param_name] = getattr(update, param if isinstance(param, str) else param[1])
80
78
 
81
79
  return params
82
80
 
@@ -105,21 +103,14 @@ def shortcut(
105
103
  index = 0
106
104
 
107
105
  for k, p in signature_params.items():
108
- if (
109
- p.kind in (p.POSITIONAL_OR_KEYWORD, p.POSITIONAL_ONLY)
110
- and len(args) > index
111
- ):
106
+ if p.kind in (p.POSITIONAL_OR_KEYWORD, p.POSITIONAL_ONLY) and len(args) > index:
112
107
  params[k] = args[index]
113
108
  index += 1
114
109
  continue
115
110
  if p.kind in (p.VAR_KEYWORD, p.VAR_POSITIONAL):
116
111
  params[k] = kwargs.copy() if p.kind is p.VAR_KEYWORD else args[index:]
117
112
  continue
118
- params[k] = (
119
- kwargs.pop(k, p.default)
120
- if p.default is not p.empty
121
- else kwargs.pop(k)
122
- )
113
+ params[k] = kwargs.pop(k, p.default) if p.default is not p.empty else kwargs.pop(k)
123
114
 
124
115
  return await executor(self, method_name, get_params(params))
125
116
 
@@ -44,9 +44,7 @@ class CallbackQueryCute(BaseCute[CallbackQuery], CallbackQuery, kw_only=True, di
44
44
  by the bot with the callback button that originated the query."""
45
45
 
46
46
  return self.message.map(
47
- lambda m: m.only()
48
- .map(lambda m: m.is_topic_message.unwrap_or(False))
49
- .unwrap_or(False)
47
+ lambda m: m.only().map(lambda m: m.is_topic_message.unwrap_or(False)).unwrap_or(False)
50
48
  )
51
49
 
52
50
  @property
@@ -219,7 +217,7 @@ class CallbackQueryCute(BaseCute[CallbackQuery], CallbackQuery, kw_only=True, di
219
217
  )
220
218
  async def edit_text(
221
219
  self,
222
- text: str | None,
220
+ text: str,
223
221
  inline_message_id: int | None = None,
224
222
  chat_id: int | str | None = None,
225
223
  message_id: int | None = None,
@@ -9,7 +9,9 @@ from .base import BaseCute, shortcut
9
9
  from .chat_member_updated import ChatMemberShortcuts, chat_member_interaction
10
10
 
11
11
 
12
- class ChatJoinRequestCute(BaseCute[ChatJoinRequest], ChatJoinRequest, ChatMemberShortcuts, kw_only=True):
12
+ class ChatJoinRequestCute(
13
+ BaseCute[ChatJoinRequest], ChatJoinRequest, ChatMemberShortcuts, kw_only=True
14
+ ):
13
15
  api: ABCAPI
14
16
 
15
17
  @property
@@ -232,7 +232,9 @@ class ChatMemberShortcuts:
232
232
  ...
233
233
 
234
234
 
235
- class ChatMemberUpdatedCute(BaseCute[ChatMemberUpdated], ChatMemberUpdated, ChatMemberShortcuts, kw_only=True):
235
+ class ChatMemberUpdatedCute(
236
+ BaseCute[ChatMemberUpdated], ChatMemberUpdated, ChatMemberShortcuts, kw_only=True
237
+ ):
236
238
  api: ABCAPI
237
239
 
238
240
  @property
@@ -71,16 +71,12 @@ async def execute_method_answer(
71
71
  link_preview_options = params.get("link_preview_options")
72
72
 
73
73
  if reply_parameters is not None and isinstance(reply_parameters, dict):
74
- reply_parameters.setdefault(
75
- "message_id", params.get("message_id", message.message_id)
76
- )
74
+ reply_parameters.setdefault("message_id", params.get("message_id", message.message_id))
77
75
  reply_parameters.setdefault("chat_id", params.get("chat_id"))
78
76
  params["reply_parameters"] = compose_reply_params(**reply_parameters)
79
77
 
80
78
  if link_preview_options is not None and isinstance(link_preview_options, dict):
81
- params["link_preview_options"] = compose_link_preview_options(
82
- **link_preview_options
83
- )
79
+ params["link_preview_options"] = compose_link_preview_options(**link_preview_options)
84
80
 
85
81
  result = await getattr(message.ctx_api, method_name)(**params)
86
82
  return result.map(
@@ -124,8 +120,7 @@ async def execute_method_edit(
124
120
  "message_thread_id": lambda x: (
125
121
  x.is_topic_message.unwrap_or(False)
126
122
  if isinstance(x, MessageCute)
127
- else bool(x.message)
128
- and getattr(x.message.unwrap().v, "is_topic_message", False)
123
+ else bool(x.message) and getattr(x.message.unwrap().v, "is_topic_message", False)
129
124
  ),
130
125
  },
131
126
  )
@@ -330,9 +325,7 @@ class MessageCute(BaseCute[Message], Message, kw_only=True):
330
325
  params=get_params(locals()),
331
326
  update=self,
332
327
  default_params={"chat_id", "message_id", "message_thread_id"},
333
- validators={
334
- "message_thread_id": lambda x: x.is_topic_message.unwrap_or(False)
335
- },
328
+ validators={"message_thread_id": lambda x: x.is_topic_message.unwrap_or(False)},
336
329
  )
337
330
  return await self.ctx_api.delete_message(**params)
338
331
 
@@ -450,9 +443,7 @@ class MessageCute(BaseCute[Message], Message, kw_only=True):
450
443
  ("from_chat_id", "chat_id"),
451
444
  "message_thread_id",
452
445
  },
453
- validators={
454
- "message_thread_id": lambda x: x.is_topic_message.unwrap_or(False)
455
- },
446
+ validators={"message_thread_id": lambda x: x.is_topic_message.unwrap_or(False)},
456
447
  )
457
448
  if isinstance(reply_parameters, dict):
458
449
  reply_parameters.setdefault("message_id", params.get("message_id"))
@@ -467,11 +458,7 @@ class MessageCute(BaseCute[Message], Message, kw_only=True):
467
458
  async def react(
468
459
  self,
469
460
  reaction: (
470
- str
471
- | ReactionEmoji
472
- | ReactionType
473
- | list[str | ReactionEmoji | ReactionType]
474
- | None
461
+ str | ReactionEmoji | ReactionType | list[str | ReactionEmoji | ReactionType] | None
475
462
  ) = None,
476
463
  chat_id: int | str | None = None,
477
464
  message_thread_id: int | None = None,
@@ -507,9 +494,7 @@ class MessageCute(BaseCute[Message], Message, kw_only=True):
507
494
  params=get_params(locals()),
508
495
  update=self,
509
496
  default_params={"chat_id", "message_id", "message_thread_id"},
510
- validators={
511
- "message_thread_id": lambda x: x.is_topic_message.unwrap_or(False)
512
- },
497
+ validators={"message_thread_id": lambda x: x.is_topic_message.unwrap_or(False)},
513
498
  )
514
499
  if reaction:
515
500
  params["reaction"] = compose_reactions(
@@ -557,9 +542,7 @@ class MessageCute(BaseCute[Message], Message, kw_only=True):
557
542
  "message_id",
558
543
  "message_thread_id",
559
544
  },
560
- validators={
561
- "message_thread_id": lambda x: x.is_topic_message.unwrap_or(False)
562
- },
545
+ validators={"message_thread_id": lambda x: x.is_topic_message.unwrap_or(False)},
563
546
  )
564
547
  return (await self.ctx_api.forward_message(**params)).map(
565
548
  lambda message: MessageCute.from_update(message, bound_api=self.api),
@@ -599,9 +582,7 @@ class MessageCute(BaseCute[Message], Message, kw_only=True):
599
582
  params=get_params(locals()),
600
583
  update=self,
601
584
  default_params={"chat_id", "message_id", "message_thread_id"},
602
- validators={
603
- "message_thread_id": lambda x: x.is_topic_message.unwrap_or(False)
604
- },
585
+ validators={"message_thread_id": lambda x: x.is_topic_message.unwrap_or(False)},
605
586
  )
606
587
  return await self.ctx_api.pin_chat_message(**params)
607
588
 
@@ -632,9 +613,7 @@ class MessageCute(BaseCute[Message], Message, kw_only=True):
632
613
  params=get_params(locals()),
633
614
  update=self,
634
615
  default_params={"chat_id", "message_id", "message_thread_id"},
635
- validators={
636
- "message_thread_id": lambda x: x.is_topic_message.unwrap_or(False)
637
- },
616
+ validators={"message_thread_id": lambda x: x.is_topic_message.unwrap_or(False)},
638
617
  )
639
618
  return await self.ctx_api.pin_chat_message(**params)
640
619
 
@@ -69,9 +69,7 @@ INPUT_MEDIA_TYPES: typing.Final[dict[str, type[InputMedia]]] = {
69
69
 
70
70
 
71
71
  def compose_reactions(
72
- reactions: (
73
- str | ReactionEmoji | ReactionType | list[str | ReactionEmoji | ReactionType]
74
- ),
72
+ reactions: (str | ReactionEmoji | ReactionType | list[str | ReactionEmoji | ReactionType]),
75
73
  /,
76
74
  ) -> list[ReactionType]:
77
75
  if not isinstance(reactions, list):
@@ -27,7 +27,7 @@ from .view import (
27
27
  RawEventView,
28
28
  ViewBox,
29
29
  )
30
- from .waiter_machine import ShortState, ShortStateStorage, WaiterMachine
30
+ from .waiter_machine import ShortState, WaiterMachine
31
31
 
32
32
  __all__ = (
33
33
  "ABCDispatch",
@@ -56,7 +56,6 @@ __all__ = (
56
56
  "MessageView",
57
57
  "RawEventView",
58
58
  "ShortState",
59
- "ShortStateStorage",
60
59
  "TelegrinderCtx",
61
60
  "ViewBox",
62
61
  "WaiterMachine",
@@ -78,9 +78,7 @@ class CompositionDispatch(ABCDispatch):
78
78
  def wrapper(func: typing.Callable):
79
79
  composition = Composition(func, is_blocking)
80
80
  if container_nodes:
81
- composition.nodes["container"] = ContainerNode.link_nodes(
82
- list(container_nodes)
83
- )
81
+ composition.nodes["container"] = ContainerNode.link_nodes(list(container_nodes))
84
82
  self.compositions.append(composition)
85
83
  return func
86
84
 
@@ -135,7 +135,9 @@ class Dispatch(
135
135
 
136
136
  async def feed(self, event: Update, api: ABCAPI) -> bool:
137
137
  logger.debug("Processing update (update_id={})", event.update_id)
138
- await self.raw_event.process(event, api)
138
+ loop = asyncio.get_running_loop()
139
+ loop.create_task(self.raw_event.process(event, api))
140
+
139
141
  for view in self.get_views().values():
140
142
  if await view.check(event):
141
143
  logger.debug(
@@ -143,10 +145,9 @@ class Dispatch(
143
145
  event.update_id,
144
146
  view.__class__.__name__,
145
147
  )
146
- await view.process(event, api)
148
+ loop.create_task(view.process(event, api))
147
149
  return True
148
150
 
149
- loop = asyncio.get_running_loop()
150
151
  ctx = Context()
151
152
  found = False
152
153
  for handler in self.default_handlers:
@@ -160,9 +161,7 @@ class Dispatch(
160
161
  def load(self, external: typing.Self) -> None:
161
162
  view_external = external.get_views()
162
163
  for name, view in self.get_views().items():
163
- assert (
164
- name in view_external
165
- ), f"View {name!r} is undefined in external dispatch."
164
+ assert name in view_external, f"View {name!r} is undefined in external dispatch."
166
165
  view.load(view_external[name])
167
166
  setattr(external, name, view)
168
167
 
@@ -18,14 +18,10 @@ if typing.TYPE_CHECKING:
18
18
 
19
19
  F = typing.TypeVar(
20
20
  "F",
21
- bound=typing.Callable[
22
- typing.Concatenate[typing.Any, ...], typing.Awaitable[typing.Any]
23
- ],
21
+ bound=typing.Callable[typing.Concatenate[typing.Any, ...], typing.Awaitable[typing.Any]],
24
22
  )
25
23
  EventT = typing.TypeVar("EventT", bound=BaseCute)
26
- ErrorHandlerT = typing.TypeVar(
27
- "ErrorHandlerT", bound=ABCErrorHandler, default=ErrorHandler
28
- )
24
+ ErrorHandlerT = typing.TypeVar("ErrorHandlerT", bound=ABCErrorHandler, default=ErrorHandler)
29
25
 
30
26
 
31
27
  @dataclasses.dataclass(repr=False)
@@ -50,12 +46,9 @@ class FuncHandler(ABCHandler[EventT], typing.Generic[EventT, F, ErrorHandlerT]):
50
46
  self.dataclass,
51
47
  self.error_handler,
52
48
  )
53
-
49
+
54
50
  async def check(self, api: ABCAPI, event: Update, ctx: Context | None = None) -> bool:
55
- if (
56
- self.update_type is not None
57
- and self.update_type != event.update_type.unwrap_or_none()
58
- ):
51
+ if self.update_type is not None and self.update_type != event.update_type.unwrap_or_none():
59
52
  return False
60
53
  ctx = ctx or Context()
61
54
  temp_ctx = ctx.copy()
@@ -66,9 +66,7 @@ class BaseReturnManager(ABCReturnManager[EventT]):
66
66
 
67
67
  async def run(self, response: typing.Any, event: EventT, ctx: Context) -> None:
68
68
  for manager in self.managers:
69
- if typing.Any in manager.types or any(
70
- type(response) is x for x in manager.types
71
- ):
69
+ if typing.Any in manager.types or any(type(response) is x for x in manager.types):
72
70
  await manager(response, event, ctx)
73
71
 
74
72
  @typing.overload
@@ -79,24 +77,22 @@ class BaseReturnManager(ABCReturnManager[EventT]):
79
77
  ]: ...
80
78
 
81
79
  @typing.overload
82
- def register_manager(self, return_type: tuple[type[T], ...]) -> typing.Callable[
80
+ def register_manager(
81
+ self,
82
+ return_type: tuple[type[T], ...],
83
+ ) -> typing.Callable[
83
84
  [typing.Callable[[tuple[T, ...], EventT, Context], typing.Awaitable[typing.Any]]],
84
85
  Manager,
85
86
  ]: ...
86
87
 
87
88
  def register_manager(
88
- self, return_type: type[T] | tuple[type[T], ...]
89
+ self,
90
+ return_type: type[T] | tuple[type[T], ...],
89
91
  ) -> typing.Callable[
90
- [
91
- typing.Callable[
92
- [T | tuple[T, ...], EventT, Context], typing.Awaitable[typing.Any]
93
- ]
94
- ],
92
+ [typing.Callable[[T | tuple[T, ...], EventT, Context], typing.Awaitable[typing.Any]]],
95
93
  Manager,
96
94
  ]:
97
- def wrapper(
98
- func: typing.Callable[[T, EventT, Context], typing.Awaitable]
99
- ) -> Manager:
95
+ def wrapper(func: typing.Callable[[T, EventT, Context], typing.Awaitable]) -> Manager:
100
96
  manager = Manager(get_union_types(return_type) or (return_type,), func) # type: ignore
101
97
  setattr(self.__class__, func.__name__, manager)
102
98
  return manager
@@ -16,23 +16,21 @@ class MessageReturnManager(BaseReturnManager[MessageCute]):
16
16
  @register_manager(list | tuple)
17
17
  @staticmethod
18
18
  async def seq_manager(
19
- value: list[str] | tuple[str, ...], event: MessageCute, ctx: Context
19
+ value: list[str] | tuple[str, ...],
20
+ event: MessageCute,
21
+ ctx: Context,
20
22
  ) -> None:
21
23
  for message in value:
22
24
  await event.answer(message)
23
25
 
24
26
  @register_manager(dict)
25
27
  @staticmethod
26
- async def dict_manager(
27
- value: dict[str, typing.Any], event: MessageCute, ctx: Context
28
- ) -> None:
28
+ async def dict_manager(value: dict[str, typing.Any], event: MessageCute, ctx: Context) -> None:
29
29
  await event.answer(**value)
30
30
 
31
31
  @register_manager(HTMLFormatter)
32
32
  @staticmethod
33
- async def htmlformatter_manager(
34
- value: HTMLFormatter, event: MessageCute, ctx: Context
35
- ) -> None:
33
+ async def htmlformatter_manager(value: HTMLFormatter, event: MessageCute, ctx: Context) -> None:
36
34
  await event.answer(value, parse_mode=HTMLFormatter.PARSE_MODE)
37
35
 
38
36
 
@@ -63,19 +63,68 @@ class BaseView(ABCView, typing.Generic[EventType]):
63
63
  for base in cls.__dict__.get("__orig_bases__", ()):
64
64
  if issubclass(typing.get_origin(base) or base, ABCView):
65
65
  for generic_type in typing.get_args(base):
66
- if issubclass(
67
- typing.get_origin(generic_type) or generic_type, BaseCute
68
- ):
66
+ if issubclass(typing.get_origin(generic_type) or generic_type, BaseCute):
69
67
  return Some(generic_type)
70
68
  return Nothing()
71
69
 
72
- @classmethod
73
- def get_raw_event(cls, update: Update) -> Option[Model]:
70
+ @staticmethod
71
+ def get_raw_event(update: Update) -> Option[Model]:
74
72
  match update.update_type:
75
73
  case Some(update_type):
76
74
  return getattr(update, update_type.value)
77
75
  case _:
78
76
  return Nothing()
77
+
78
+ @typing.overload
79
+ @classmethod
80
+ def to_handler(
81
+ cls,
82
+ *rules: ABCRule[EventType],
83
+ ) -> typing.Callable[
84
+ [FuncType[EventType]],
85
+ FuncHandler[EventType, FuncType[EventType], ErrorHandler[EventType]],
86
+ ]: ...
87
+
88
+ @typing.overload
89
+ @classmethod
90
+ def to_handler(
91
+ cls,
92
+ *rules: ABCRule[EventType],
93
+ error_handler: ErrorHandlerT,
94
+ is_blocking: bool = True,
95
+ ) -> typing.Callable[
96
+ [FuncType[EventType]], FuncHandler[EventType, FuncType[EventType], ErrorHandlerT]
97
+ ]: ...
98
+
99
+ @typing.overload
100
+ @classmethod
101
+ def to_handler(
102
+ cls,
103
+ *rules: ABCRule[EventType],
104
+ error_handler: typing.Literal[None] = None,
105
+ is_blocking: bool = True,
106
+ ) -> typing.Callable[
107
+ [FuncType[EventType]],
108
+ FuncHandler[EventType, FuncType[EventType], ErrorHandler[EventType]],
109
+ ]: ...
110
+
111
+ @classmethod
112
+ def to_handler( # type: ignore
113
+ cls,
114
+ *rules: ABCRule[EventType],
115
+ error_handler: ABCErrorHandler | None = None,
116
+ is_blocking: bool = True,
117
+ ):
118
+ def wrapper(func: FuncType[EventType]):
119
+ return FuncHandler(
120
+ func,
121
+ list(rules),
122
+ is_blocking=is_blocking,
123
+ dataclass=None,
124
+ error_handler=error_handler or ErrorHandler(),
125
+ )
126
+
127
+ return wrapper
79
128
 
80
129
  @typing.overload
81
130
  def __call__(
@@ -12,16 +12,12 @@ from .inline_query import InlineQueryView
12
12
  from .message import MessageView
13
13
  from .raw import RawEventView
14
14
 
15
- CallbackQueryViewT = typing.TypeVar(
16
- "CallbackQueryViewT", bound=ABCView, default=CallbackQueryView
17
- )
15
+ CallbackQueryViewT = typing.TypeVar("CallbackQueryViewT", bound=ABCView, default=CallbackQueryView)
18
16
  ChatJoinRequestViewT = typing.TypeVar(
19
17
  "ChatJoinRequestViewT", bound=ABCView, default=ChatJoinRequestView
20
18
  )
21
19
  ChatMemberViewT = typing.TypeVar("ChatMemberViewT", bound=ABCView, default=ChatMemberView)
22
- InlineQueryViewT = typing.TypeVar(
23
- "InlineQueryViewT", bound=ABCView, default=InlineQueryView
24
- )
20
+ InlineQueryViewT = typing.TypeVar("InlineQueryViewT", bound=ABCView, default=InlineQueryView)
25
21
  MessageViewT = typing.TypeVar("MessageViewT", bound=ABCView, default=MessageView)
26
22
  RawEventViewT = typing.TypeVar("RawEventViewT", bound=ABCView, default=RawEventView)
27
23
 
@@ -100,11 +96,7 @@ class ViewBox(
100
96
  def get_views(self) -> dict[str, ABCView]:
101
97
  """Get all views."""
102
98
 
103
- return {
104
- name: view
105
- for name, view in self.__dict__.items()
106
- if isinstance(view, ABCView)
107
- }
99
+ return {name: view for name, view in self.__dict__.items() if isinstance(view, ABCView)}
108
100
 
109
101
 
110
102
  __all__ = ("ViewBox",)
@@ -41,9 +41,7 @@ class RawEventView(BaseView[UpdateCute]):
41
41
  update_type: UpdateType,
42
42
  *rules: ABCRule[UpdateCute],
43
43
  dataclass: type[T],
44
- ) -> typing.Callable[
45
- [FuncType[T]], FuncHandler[UpdateCute, FuncType[T], ErrorHandler[T]]
46
- ]: ...
44
+ ) -> typing.Callable[[FuncType[T]], FuncHandler[UpdateCute, FuncType[T], ErrorHandler[T]]]: ...
47
45
 
48
46
  @typing.overload
49
47
  def __call__(
@@ -64,9 +62,7 @@ class RawEventView(BaseView[UpdateCute]):
64
62
  dataclass: type[T],
65
63
  error_handler: ErrorHandlerT,
66
64
  is_blocking: bool = True,
67
- ) -> typing.Callable[
68
- [FuncType[T]], FuncHandler[UpdateCute, FuncType[T], ErrorHandlerT]
69
- ]: ...
65
+ ) -> typing.Callable[[FuncType[T]], FuncHandler[UpdateCute, FuncType[T], ErrorHandlerT]]: ...
70
66
 
71
67
  @typing.overload
72
68
  def __call__(
@@ -1,10 +1,9 @@
1
- from .machine import ShortStateStorage, WaiterMachine
1
+ from .machine import WaiterMachine
2
2
  from .middleware import WaiterMiddleware
3
3
  from .short_state import ShortState
4
4
 
5
5
  __all__ = (
6
6
  "ShortState",
7
- "ShortStateStorage",
8
7
  "WaiterMachine",
9
8
  "WaiterMiddleware",
10
9
  )