telegrinder 0.3.1__py3-none-any.whl → 0.3.2__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 (164) hide show
  1. telegrinder/__init__.py +144 -144
  2. telegrinder/api/__init__.py +8 -8
  3. telegrinder/api/api.py +93 -93
  4. telegrinder/api/error.py +16 -16
  5. telegrinder/api/response.py +20 -20
  6. telegrinder/api/token.py +36 -36
  7. telegrinder/bot/__init__.py +66 -66
  8. telegrinder/bot/bot.py +76 -76
  9. telegrinder/bot/cute_types/__init__.py +11 -11
  10. telegrinder/bot/cute_types/base.py +258 -234
  11. telegrinder/bot/cute_types/callback_query.py +382 -382
  12. telegrinder/bot/cute_types/chat_join_request.py +61 -61
  13. telegrinder/bot/cute_types/chat_member_updated.py +160 -160
  14. telegrinder/bot/cute_types/inline_query.py +53 -53
  15. telegrinder/bot/cute_types/message.py +2631 -2631
  16. telegrinder/bot/cute_types/update.py +75 -75
  17. telegrinder/bot/cute_types/utils.py +92 -92
  18. telegrinder/bot/dispatch/__init__.py +55 -55
  19. telegrinder/bot/dispatch/abc.py +77 -77
  20. telegrinder/bot/dispatch/context.py +92 -92
  21. telegrinder/bot/dispatch/dispatch.py +202 -201
  22. telegrinder/bot/dispatch/handler/__init__.py +13 -13
  23. telegrinder/bot/dispatch/handler/abc.py +24 -24
  24. telegrinder/bot/dispatch/handler/audio_reply.py +44 -44
  25. telegrinder/bot/dispatch/handler/base.py +57 -57
  26. telegrinder/bot/dispatch/handler/document_reply.py +44 -44
  27. telegrinder/bot/dispatch/handler/func.py +128 -123
  28. telegrinder/bot/dispatch/handler/media_group_reply.py +43 -43
  29. telegrinder/bot/dispatch/handler/message_reply.py +36 -36
  30. telegrinder/bot/dispatch/handler/photo_reply.py +44 -44
  31. telegrinder/bot/dispatch/handler/sticker_reply.py +37 -37
  32. telegrinder/bot/dispatch/handler/video_reply.py +44 -44
  33. telegrinder/bot/dispatch/middleware/__init__.py +3 -3
  34. telegrinder/bot/dispatch/middleware/abc.py +16 -16
  35. telegrinder/bot/dispatch/process.py +132 -132
  36. telegrinder/bot/dispatch/return_manager/__init__.py +13 -13
  37. telegrinder/bot/dispatch/return_manager/abc.py +108 -108
  38. telegrinder/bot/dispatch/return_manager/callback_query.py +20 -20
  39. telegrinder/bot/dispatch/return_manager/inline_query.py +15 -15
  40. telegrinder/bot/dispatch/return_manager/message.py +36 -36
  41. telegrinder/bot/dispatch/view/__init__.py +13 -13
  42. telegrinder/bot/dispatch/view/abc.py +41 -41
  43. telegrinder/bot/dispatch/view/base.py +200 -211
  44. telegrinder/bot/dispatch/view/box.py +129 -129
  45. telegrinder/bot/dispatch/view/callback_query.py +17 -17
  46. telegrinder/bot/dispatch/view/chat_join_request.py +16 -16
  47. telegrinder/bot/dispatch/view/chat_member.py +39 -39
  48. telegrinder/bot/dispatch/view/inline_query.py +17 -17
  49. telegrinder/bot/dispatch/view/message.py +44 -44
  50. telegrinder/bot/dispatch/view/raw.py +114 -118
  51. telegrinder/bot/dispatch/waiter_machine/__init__.py +17 -17
  52. telegrinder/bot/dispatch/waiter_machine/actions.py +13 -13
  53. telegrinder/bot/dispatch/waiter_machine/hasher/__init__.py +8 -8
  54. telegrinder/bot/dispatch/waiter_machine/hasher/callback.py +57 -57
  55. telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +57 -57
  56. telegrinder/bot/dispatch/waiter_machine/hasher/message.py +53 -53
  57. telegrinder/bot/dispatch/waiter_machine/hasher/state.py +19 -19
  58. telegrinder/bot/dispatch/waiter_machine/machine.py +168 -170
  59. telegrinder/bot/dispatch/waiter_machine/middleware.py +89 -89
  60. telegrinder/bot/dispatch/waiter_machine/short_state.py +65 -65
  61. telegrinder/bot/polling/__init__.py +4 -4
  62. telegrinder/bot/polling/abc.py +25 -25
  63. telegrinder/bot/polling/polling.py +131 -131
  64. telegrinder/bot/rules/__init__.py +62 -62
  65. telegrinder/bot/rules/abc.py +238 -238
  66. telegrinder/bot/rules/adapter/__init__.py +9 -9
  67. telegrinder/bot/rules/adapter/abc.py +29 -29
  68. telegrinder/bot/rules/adapter/errors.py +5 -5
  69. telegrinder/bot/rules/adapter/event.py +76 -76
  70. telegrinder/bot/rules/adapter/node.py +48 -48
  71. telegrinder/bot/rules/adapter/raw_update.py +30 -30
  72. telegrinder/bot/rules/callback_data.py +171 -171
  73. telegrinder/bot/rules/chat_join.py +48 -48
  74. telegrinder/bot/rules/command.py +126 -126
  75. telegrinder/bot/rules/enum_text.py +36 -36
  76. telegrinder/bot/rules/func.py +26 -26
  77. telegrinder/bot/rules/fuzzy.py +24 -24
  78. telegrinder/bot/rules/inline.py +60 -60
  79. telegrinder/bot/rules/integer.py +20 -20
  80. telegrinder/bot/rules/is_from.py +146 -146
  81. telegrinder/bot/rules/markup.py +43 -43
  82. telegrinder/bot/rules/mention.py +14 -14
  83. telegrinder/bot/rules/message.py +17 -17
  84. telegrinder/bot/rules/message_entities.py +35 -35
  85. telegrinder/bot/rules/node.py +27 -27
  86. telegrinder/bot/rules/regex.py +37 -37
  87. telegrinder/bot/rules/rule_enum.py +72 -72
  88. telegrinder/bot/rules/start.py +42 -42
  89. telegrinder/bot/rules/state.py +37 -37
  90. telegrinder/bot/rules/text.py +33 -33
  91. telegrinder/bot/rules/update.py +15 -15
  92. telegrinder/bot/scenario/__init__.py +5 -5
  93. telegrinder/bot/scenario/abc.py +19 -19
  94. telegrinder/bot/scenario/checkbox.py +167 -147
  95. telegrinder/bot/scenario/choice.py +46 -44
  96. telegrinder/client/__init__.py +4 -4
  97. telegrinder/client/abc.py +75 -75
  98. telegrinder/client/aiohttp.py +130 -130
  99. telegrinder/model.py +244 -244
  100. telegrinder/modules.py +237 -237
  101. telegrinder/msgspec_json.py +14 -14
  102. telegrinder/msgspec_utils.py +410 -410
  103. telegrinder/node/__init__.py +20 -20
  104. telegrinder/node/attachment.py +92 -92
  105. telegrinder/node/base.py +143 -144
  106. telegrinder/node/callback_query.py +14 -14
  107. telegrinder/node/command.py +33 -33
  108. telegrinder/node/composer.py +196 -184
  109. telegrinder/node/container.py +27 -27
  110. telegrinder/node/event.py +71 -73
  111. telegrinder/node/me.py +16 -16
  112. telegrinder/node/message.py +14 -14
  113. telegrinder/node/polymorphic.py +48 -52
  114. telegrinder/node/rule.py +76 -76
  115. telegrinder/node/scope.py +38 -38
  116. telegrinder/node/source.py +71 -71
  117. telegrinder/node/text.py +21 -21
  118. telegrinder/node/tools/__init__.py +3 -3
  119. telegrinder/node/tools/generator.py +40 -40
  120. telegrinder/node/update.py +15 -15
  121. telegrinder/rules.py +0 -0
  122. telegrinder/tools/__init__.py +74 -74
  123. telegrinder/tools/buttons.py +79 -79
  124. telegrinder/tools/error_handler/__init__.py +7 -7
  125. telegrinder/tools/error_handler/abc.py +33 -33
  126. telegrinder/tools/error_handler/error.py +9 -9
  127. telegrinder/tools/error_handler/error_handler.py +193 -193
  128. telegrinder/tools/formatting/__init__.py +46 -46
  129. telegrinder/tools/formatting/html.py +308 -308
  130. telegrinder/tools/formatting/links.py +33 -33
  131. telegrinder/tools/formatting/spec_html_formats.py +111 -111
  132. telegrinder/tools/functional.py +12 -12
  133. telegrinder/tools/global_context/__init__.py +7 -7
  134. telegrinder/tools/global_context/abc.py +63 -63
  135. telegrinder/tools/global_context/global_context.py +412 -412
  136. telegrinder/tools/global_context/telegrinder_ctx.py +27 -27
  137. telegrinder/tools/i18n/__init__.py +12 -12
  138. telegrinder/tools/i18n/abc.py +32 -32
  139. telegrinder/tools/i18n/middleware/__init__.py +3 -3
  140. telegrinder/tools/i18n/middleware/abc.py +25 -25
  141. telegrinder/tools/i18n/simple.py +43 -43
  142. telegrinder/tools/kb_set/__init__.py +4 -4
  143. telegrinder/tools/kb_set/base.py +15 -15
  144. telegrinder/tools/kb_set/yaml.py +63 -63
  145. telegrinder/tools/keyboard.py +128 -128
  146. telegrinder/tools/limited_dict.py +37 -37
  147. telegrinder/tools/loop_wrapper/__init__.py +4 -4
  148. telegrinder/tools/loop_wrapper/abc.py +15 -15
  149. telegrinder/tools/loop_wrapper/loop_wrapper.py +216 -216
  150. telegrinder/tools/magic.py +168 -168
  151. telegrinder/tools/parse_mode.py +6 -6
  152. telegrinder/tools/state_storage/__init__.py +4 -4
  153. telegrinder/tools/state_storage/abc.py +35 -35
  154. telegrinder/tools/state_storage/memory.py +25 -25
  155. telegrinder/types/__init__.py +6 -6
  156. telegrinder/types/enums.py +672 -672
  157. telegrinder/types/methods.py +4633 -4633
  158. telegrinder/types/objects.py +6317 -6317
  159. telegrinder/verification_utils.py +32 -32
  160. {telegrinder-0.3.1.dist-info → telegrinder-0.3.2.dist-info}/LICENSE +22 -22
  161. {telegrinder-0.3.1.dist-info → telegrinder-0.3.2.dist-info}/METADATA +1 -1
  162. telegrinder-0.3.2.dist-info/RECORD +164 -0
  163. telegrinder-0.3.1.dist-info/RECORD +0 -164
  164. {telegrinder-0.3.1.dist-info → telegrinder-0.3.2.dist-info}/WHEEL +0 -0
@@ -1,238 +1,238 @@
1
- import inspect
2
- from abc import ABC, abstractmethod
3
- from functools import cached_property
4
-
5
- import typing_extensions as typing
6
-
7
- from telegrinder.bot.cute_types import MessageCute, UpdateCute
8
- from telegrinder.bot.dispatch.context import Context
9
- from telegrinder.bot.dispatch.process import check_rule
10
- from telegrinder.bot.rules.adapter import ABCAdapter, RawUpdateAdapter
11
- from telegrinder.bot.rules.adapter.node import Event
12
- from telegrinder.node.base import Node, get_nodes, is_node
13
- from telegrinder.tools.i18n.abc import ABCTranslator
14
- from telegrinder.tools.magic import (
15
- cache_translation,
16
- get_annotations,
17
- get_cached_translation,
18
- get_default_args,
19
- )
20
- from telegrinder.types.objects import Update as UpdateObject
21
-
22
- if typing.TYPE_CHECKING:
23
- from telegrinder.node.composer import NodeCollection
24
-
25
- AdaptTo = typing.TypeVar("AdaptTo", default=typing.Any, contravariant=True)
26
-
27
- CheckResult: typing.TypeAlias = bool | typing.Coroutine[typing.Any, typing.Any, bool]
28
- Message: typing.TypeAlias = MessageCute
29
- Update: typing.TypeAlias = UpdateCute
30
-
31
-
32
- def with_caching_translations(func: typing.Callable[..., typing.Any]):
33
- """Should be used as decorator for .translate method. Caches rule translations."""
34
-
35
- async def wrapper(self: "ABCRule", translator: ABCTranslator):
36
- if translation := get_cached_translation(self, translator.locale):
37
- return translation
38
- translation = await func(self, translator)
39
- cache_translation(self, translator.locale, translation)
40
- return translation
41
-
42
- return wrapper
43
-
44
-
45
- class ABCRule(ABC, typing.Generic[AdaptTo]):
46
- adapter: ABCAdapter[UpdateObject, AdaptTo]
47
- requires: list["ABCRule"] = []
48
-
49
- if typing.TYPE_CHECKING:
50
-
51
- @typing.overload
52
- def check(self) -> CheckResult: ...
53
-
54
- @typing.overload
55
- def check(self, event: AdaptTo, /) -> CheckResult: ...
56
-
57
- @typing.overload
58
- def check(self, event: AdaptTo, ctx: Context, /) -> CheckResult: ...
59
-
60
- @typing.overload
61
- def check(
62
- self,
63
- event: AdaptTo,
64
- ctx: Context,
65
- /,
66
- *args: typing.Any,
67
- **kwargs: typing.Any,
68
- ) -> CheckResult: ...
69
-
70
- @typing.overload
71
- def check(self, event: AdaptTo, /, *args: typing.Any, **kwargs: typing.Any) -> CheckResult: ...
72
-
73
- @typing.overload
74
- def check(self, ctx: Context, /, *args: typing.Any, **kwargs: typing.Any) -> CheckResult: ...
75
-
76
- @abstractmethod
77
- def check(self, *args: typing.Any, **kwargs: typing.Any) -> CheckResult:
78
- pass
79
- else:
80
- adapter = RawUpdateAdapter()
81
-
82
- @abstractmethod
83
- def check(self, *args, **kwargs):
84
- pass
85
-
86
- def __init_subclass__(cls, requires: list["ABCRule"] | None = None) -> None:
87
- """Merges requirements from inherited classes and rule-specific requirements."""
88
-
89
- requirements = []
90
- for base in inspect.getmro(cls):
91
- if issubclass(base, ABCRule) and base != cls:
92
- requirements.extend(base.requires or ()) # type: ignore
93
-
94
- requirements.extend(requires or ())
95
- cls.requires = list(dict.fromkeys(requirements))
96
-
97
- def __and__(self, other: "ABCRule") -> "AndRule":
98
- """And Rule.
99
-
100
- ```python
101
- rule = HasText() & HasCaption()
102
- rule #> AndRule(HasText(), HasCaption()) -> True if all rules in an AndRule are True, otherwise False.
103
- ```
104
- """
105
-
106
- return AndRule(self, other)
107
-
108
- def __or__(self, other: "ABCRule") -> "OrRule":
109
- """Or Rule.
110
-
111
- ```python
112
- rule = HasText() | HasCaption()
113
- rule #> OrRule(HasText(), HasCaption()) -> True if any rule in an OrRule are True, otherwise False.
114
- ```
115
- """
116
-
117
- return OrRule(self, other)
118
-
119
- def __invert__(self) -> "NotRule":
120
- """Not Rule.
121
-
122
- ```python
123
- rule = ~HasText()
124
- rule # NotRule(HasText()) -> True if rule returned False, otherwise False.
125
- ```
126
- """
127
-
128
- return NotRule(self)
129
-
130
- def __repr__(self) -> str:
131
- return "<{}: adapter={!r}>".format(
132
- self.__class__.__name__,
133
- self.adapter,
134
- )
135
-
136
- @cached_property
137
- def required_nodes(self) -> dict[str, type[Node]]:
138
- return get_nodes(self.check)
139
-
140
- def as_optional(self) -> "ABCRule":
141
- return self | Always()
142
-
143
- def should_fail(self) -> "ABCRule":
144
- return self & Never()
145
-
146
- async def bounding_check(
147
- self,
148
- adapted_value: AdaptTo,
149
- ctx: Context,
150
- node_col: "NodeCollection | None" = None,
151
- ) -> bool:
152
- bound_check_rule = self.check
153
- kw = {}
154
- node_col_values = node_col.values if node_col is not None else {}
155
- temp_ctx = get_default_args(bound_check_rule) | ctx
156
-
157
- for i, (k, v) in enumerate(get_annotations(bound_check_rule).items()):
158
- if (isinstance(adapted_value, Event) and i == 0) or ( # First arg is Event
159
- isinstance(v, type) and isinstance(adapted_value, v)
160
- ):
161
- kw[k] = adapted_value if not isinstance(adapted_value, Event) else adapted_value.obj
162
- elif is_node(v):
163
- assert k in node_col_values, "Node is undefined, error while bounding."
164
- kw[k] = node_col_values[k]
165
- elif k in temp_ctx:
166
- kw[k] = temp_ctx[k]
167
- elif v is Context:
168
- kw[k] = ctx
169
- else:
170
- raise LookupError(
171
- f"Cannot bound {k!r} of type {v!r} to '{self.__class__.__qualname__}.check()', "
172
- "because it cannot be resolved."
173
- )
174
-
175
- result = bound_check_rule(**kw) # type: ignore
176
- if inspect.isawaitable(result):
177
- result = await result
178
- return result
179
-
180
- async def translate(self, translator: ABCTranslator) -> typing.Self:
181
- return self
182
-
183
-
184
- class AndRule(ABCRule):
185
- def __init__(self, *rules: ABCRule) -> None:
186
- self.rules = rules
187
-
188
- async def check(self, event: Update, ctx: Context) -> bool:
189
- ctx_copy = ctx.copy()
190
- for rule in self.rules:
191
- if not await check_rule(event.ctx_api, rule, event, ctx_copy):
192
- return False
193
- ctx |= ctx_copy
194
- return True
195
-
196
-
197
- class OrRule(ABCRule):
198
- def __init__(self, *rules: ABCRule) -> None:
199
- self.rules = rules
200
-
201
- async def check(self, event: Update, ctx: Context) -> bool:
202
- for rule in self.rules:
203
- ctx_copy = ctx.copy()
204
- if await check_rule(event.ctx_api, rule, event, ctx_copy):
205
- ctx |= ctx_copy
206
- return True
207
- return False
208
-
209
-
210
- class NotRule(ABCRule):
211
- def __init__(self, rule: ABCRule) -> None:
212
- self.rule = rule
213
-
214
- async def check(self, event: Update, ctx: Context) -> bool:
215
- ctx_copy = ctx.copy()
216
- return not await check_rule(event.ctx_api, self.rule, event, ctx_copy)
217
-
218
-
219
- class Never(ABCRule):
220
- async def check(self) -> typing.Literal[False]:
221
- return False
222
-
223
-
224
- class Always(ABCRule):
225
- async def check(self) -> typing.Literal[True]:
226
- return True
227
-
228
-
229
- __all__ = (
230
- "ABCRule",
231
- "Always",
232
- "AndRule",
233
- "Never",
234
- "NotRule",
235
- "OrRule",
236
- "CheckResult",
237
- "with_caching_translations",
238
- )
1
+ import inspect
2
+ from abc import ABC, abstractmethod
3
+ from functools import cached_property
4
+
5
+ import typing_extensions as typing
6
+
7
+ from telegrinder.bot.cute_types import MessageCute, UpdateCute
8
+ from telegrinder.bot.dispatch.context import Context
9
+ from telegrinder.bot.dispatch.process import check_rule
10
+ from telegrinder.bot.rules.adapter import ABCAdapter, RawUpdateAdapter
11
+ from telegrinder.bot.rules.adapter.node import Event
12
+ from telegrinder.node.base import Node, get_nodes, is_node
13
+ from telegrinder.tools.i18n.abc import ABCTranslator
14
+ from telegrinder.tools.magic import (
15
+ cache_translation,
16
+ get_annotations,
17
+ get_cached_translation,
18
+ get_default_args,
19
+ )
20
+ from telegrinder.types.objects import Update as UpdateObject
21
+
22
+ if typing.TYPE_CHECKING:
23
+ from telegrinder.node.composer import NodeCollection
24
+
25
+ AdaptTo = typing.TypeVar("AdaptTo", default=typing.Any, contravariant=True)
26
+
27
+ CheckResult: typing.TypeAlias = bool | typing.Coroutine[typing.Any, typing.Any, bool]
28
+ Message: typing.TypeAlias = MessageCute
29
+ Update: typing.TypeAlias = UpdateCute
30
+
31
+
32
+ def with_caching_translations(func: typing.Callable[..., typing.Any]):
33
+ """Should be used as decorator for .translate method. Caches rule translations."""
34
+
35
+ async def wrapper(self: "ABCRule", translator: ABCTranslator):
36
+ if translation := get_cached_translation(self, translator.locale):
37
+ return translation
38
+ translation = await func(self, translator)
39
+ cache_translation(self, translator.locale, translation)
40
+ return translation
41
+
42
+ return wrapper
43
+
44
+
45
+ class ABCRule(ABC, typing.Generic[AdaptTo]):
46
+ adapter: ABCAdapter[UpdateObject, AdaptTo]
47
+ requires: list["ABCRule"] = []
48
+
49
+ if typing.TYPE_CHECKING:
50
+
51
+ @typing.overload
52
+ def check(self) -> CheckResult: ...
53
+
54
+ @typing.overload
55
+ def check(self, event: AdaptTo, /) -> CheckResult: ...
56
+
57
+ @typing.overload
58
+ def check(self, event: AdaptTo, ctx: Context, /) -> CheckResult: ...
59
+
60
+ @typing.overload
61
+ def check(
62
+ self,
63
+ event: AdaptTo,
64
+ ctx: Context,
65
+ /,
66
+ *args: typing.Any,
67
+ **kwargs: typing.Any,
68
+ ) -> CheckResult: ...
69
+
70
+ @typing.overload
71
+ def check(self, event: AdaptTo, /, *args: typing.Any, **kwargs: typing.Any) -> CheckResult: ...
72
+
73
+ @typing.overload
74
+ def check(self, ctx: Context, /, *args: typing.Any, **kwargs: typing.Any) -> CheckResult: ...
75
+
76
+ @abstractmethod
77
+ def check(self, *args: typing.Any, **kwargs: typing.Any) -> CheckResult:
78
+ pass
79
+ else:
80
+ adapter = RawUpdateAdapter()
81
+
82
+ @abstractmethod
83
+ def check(self, *args, **kwargs):
84
+ pass
85
+
86
+ def __init_subclass__(cls, requires: list["ABCRule"] | None = None) -> None:
87
+ """Merges requirements from inherited classes and rule-specific requirements."""
88
+
89
+ requirements = []
90
+ for base in inspect.getmro(cls):
91
+ if issubclass(base, ABCRule) and base != cls:
92
+ requirements.extend(base.requires or ()) # type: ignore
93
+
94
+ requirements.extend(requires or ())
95
+ cls.requires = list(dict.fromkeys(requirements))
96
+
97
+ def __and__(self, other: "ABCRule") -> "AndRule":
98
+ """And Rule.
99
+
100
+ ```python
101
+ rule = HasText() & HasCaption()
102
+ rule #> AndRule(HasText(), HasCaption()) -> True if all rules in an AndRule are True, otherwise False.
103
+ ```
104
+ """
105
+
106
+ return AndRule(self, other)
107
+
108
+ def __or__(self, other: "ABCRule") -> "OrRule":
109
+ """Or Rule.
110
+
111
+ ```python
112
+ rule = HasText() | HasCaption()
113
+ rule #> OrRule(HasText(), HasCaption()) -> True if any rule in an OrRule are True, otherwise False.
114
+ ```
115
+ """
116
+
117
+ return OrRule(self, other)
118
+
119
+ def __invert__(self) -> "NotRule":
120
+ """Not Rule.
121
+
122
+ ```python
123
+ rule = ~HasText()
124
+ rule # NotRule(HasText()) -> True if rule returned False, otherwise False.
125
+ ```
126
+ """
127
+
128
+ return NotRule(self)
129
+
130
+ def __repr__(self) -> str:
131
+ return "<{}: adapter={!r}>".format(
132
+ self.__class__.__name__,
133
+ self.adapter,
134
+ )
135
+
136
+ @cached_property
137
+ def required_nodes(self) -> dict[str, type[Node]]:
138
+ return get_nodes(self.check)
139
+
140
+ def as_optional(self) -> "ABCRule":
141
+ return self | Always()
142
+
143
+ def should_fail(self) -> "ABCRule":
144
+ return self & Never()
145
+
146
+ async def bounding_check(
147
+ self,
148
+ adapted_value: AdaptTo,
149
+ ctx: Context,
150
+ node_col: "NodeCollection | None" = None,
151
+ ) -> bool:
152
+ bound_check_rule = self.check
153
+ kw = {}
154
+ node_col_values = node_col.values if node_col is not None else {}
155
+ temp_ctx = get_default_args(bound_check_rule) | ctx
156
+
157
+ for i, (k, v) in enumerate(get_annotations(bound_check_rule).items()):
158
+ if (isinstance(adapted_value, Event) and i == 0) or ( # First arg is Event
159
+ isinstance(v, type) and isinstance(adapted_value, v)
160
+ ):
161
+ kw[k] = adapted_value if not isinstance(adapted_value, Event) else adapted_value.obj
162
+ elif is_node(v):
163
+ assert k in node_col_values, "Node is undefined, error while bounding."
164
+ kw[k] = node_col_values[k]
165
+ elif k in temp_ctx:
166
+ kw[k] = temp_ctx[k]
167
+ elif v is Context:
168
+ kw[k] = ctx
169
+ else:
170
+ raise LookupError(
171
+ f"Cannot bound {k!r} of type {v!r} to '{self.__class__.__qualname__}.check()', "
172
+ "because it cannot be resolved."
173
+ )
174
+
175
+ result = bound_check_rule(**kw) # type: ignore
176
+ if inspect.isawaitable(result):
177
+ result = await result
178
+ return result
179
+
180
+ async def translate(self, translator: ABCTranslator) -> typing.Self:
181
+ return self
182
+
183
+
184
+ class AndRule(ABCRule):
185
+ def __init__(self, *rules: ABCRule) -> None:
186
+ self.rules = rules
187
+
188
+ async def check(self, event: Update, ctx: Context) -> bool:
189
+ ctx_copy = ctx.copy()
190
+ for rule in self.rules:
191
+ if not await check_rule(event.ctx_api, rule, event, ctx_copy):
192
+ return False
193
+ ctx |= ctx_copy
194
+ return True
195
+
196
+
197
+ class OrRule(ABCRule):
198
+ def __init__(self, *rules: ABCRule) -> None:
199
+ self.rules = rules
200
+
201
+ async def check(self, event: Update, ctx: Context) -> bool:
202
+ for rule in self.rules:
203
+ ctx_copy = ctx.copy()
204
+ if await check_rule(event.ctx_api, rule, event, ctx_copy):
205
+ ctx |= ctx_copy
206
+ return True
207
+ return False
208
+
209
+
210
+ class NotRule(ABCRule):
211
+ def __init__(self, rule: ABCRule) -> None:
212
+ self.rule = rule
213
+
214
+ async def check(self, event: Update, ctx: Context) -> bool:
215
+ ctx_copy = ctx.copy()
216
+ return not await check_rule(event.ctx_api, self.rule, event, ctx_copy)
217
+
218
+
219
+ class Never(ABCRule):
220
+ async def check(self) -> typing.Literal[False]:
221
+ return False
222
+
223
+
224
+ class Always(ABCRule):
225
+ async def check(self) -> typing.Literal[True]:
226
+ return True
227
+
228
+
229
+ __all__ = (
230
+ "ABCRule",
231
+ "Always",
232
+ "AndRule",
233
+ "Never",
234
+ "NotRule",
235
+ "OrRule",
236
+ "CheckResult",
237
+ "with_caching_translations",
238
+ )
@@ -1,14 +1,14 @@
1
- from telegrinder.bot.rules.adapter.abc import ABCAdapter, Event
2
- from telegrinder.bot.rules.adapter.errors import AdapterError
3
- from telegrinder.bot.rules.adapter.event import EventAdapter
4
- from telegrinder.bot.rules.adapter.node import NodeAdapter
5
- from telegrinder.bot.rules.adapter.raw_update import RawUpdateAdapter
6
-
7
- __all__ = (
1
+ from telegrinder.bot.rules.adapter.abc import ABCAdapter, Event
2
+ from telegrinder.bot.rules.adapter.errors import AdapterError
3
+ from telegrinder.bot.rules.adapter.event import EventAdapter
4
+ from telegrinder.bot.rules.adapter.node import NodeAdapter
5
+ from telegrinder.bot.rules.adapter.raw_update import RawUpdateAdapter
6
+
7
+ __all__ = (
8
8
  "ABCAdapter",
9
9
  "AdapterError",
10
10
  "Event",
11
11
  "EventAdapter",
12
12
  "NodeAdapter",
13
- "RawUpdateAdapter",
14
- )
13
+ "RawUpdateAdapter",
14
+ )
@@ -1,29 +1,29 @@
1
- import abc
2
- import dataclasses
3
- import typing
4
-
5
- from fntypes.result import Result
6
-
7
- from telegrinder.api import API
8
- from telegrinder.bot.dispatch.context import Context
9
- from telegrinder.bot.rules.adapter.errors import AdapterError
10
- from telegrinder.model import Model
11
-
12
- From = typing.TypeVar("From", bound=Model)
13
- To = typing.TypeVar("To")
14
-
15
-
16
- class ABCAdapter(abc.ABC, typing.Generic[From, To]):
17
- ADAPTED_VALUE_KEY: str | None = None
18
-
19
- @abc.abstractmethod
20
- async def adapt(self, api: API, update: From, context: Context) -> Result[To, AdapterError]:
21
- pass
22
-
23
-
24
- @dataclasses.dataclass(slots=True)
25
- class Event(typing.Generic[To]):
26
- obj: To
27
-
28
-
29
- __all__ = ("ABCAdapter", "Event")
1
+ import abc
2
+ import dataclasses
3
+ import typing
4
+
5
+ from fntypes.result import Result
6
+
7
+ from telegrinder.api import API
8
+ from telegrinder.bot.dispatch.context import Context
9
+ from telegrinder.bot.rules.adapter.errors import AdapterError
10
+ from telegrinder.model import Model
11
+
12
+ From = typing.TypeVar("From", bound=Model)
13
+ To = typing.TypeVar("To")
14
+
15
+
16
+ class ABCAdapter(abc.ABC, typing.Generic[From, To]):
17
+ ADAPTED_VALUE_KEY: str | None = None
18
+
19
+ @abc.abstractmethod
20
+ async def adapt(self, api: API, update: From, context: Context) -> Result[To, AdapterError]:
21
+ pass
22
+
23
+
24
+ @dataclasses.dataclass(slots=True)
25
+ class Event(typing.Generic[To]):
26
+ obj: To
27
+
28
+
29
+ __all__ = ("ABCAdapter", "Event")
@@ -1,5 +1,5 @@
1
- class AdapterError(RuntimeError):
2
- pass
3
-
4
-
5
- __all__ = ("AdapterError",)
1
+ class AdapterError(RuntimeError):
2
+ pass
3
+
4
+
5
+ __all__ = ("AdapterError",)