telegrinder 0.3.4.post1__py3-none-any.whl → 0.4.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.
Potentially problematic release.
This version of telegrinder might be problematic. Click here for more details.
- telegrinder/__init__.py +30 -31
- telegrinder/api/__init__.py +2 -1
- telegrinder/api/api.py +28 -20
- telegrinder/api/error.py +8 -4
- telegrinder/api/response.py +2 -2
- telegrinder/api/token.py +2 -2
- telegrinder/bot/__init__.py +6 -0
- telegrinder/bot/bot.py +38 -31
- telegrinder/bot/cute_types/__init__.py +2 -0
- telegrinder/bot/cute_types/base.py +54 -128
- telegrinder/bot/cute_types/callback_query.py +76 -61
- telegrinder/bot/cute_types/chat_join_request.py +4 -3
- telegrinder/bot/cute_types/chat_member_updated.py +28 -31
- telegrinder/bot/cute_types/inline_query.py +5 -4
- telegrinder/bot/cute_types/message.py +555 -602
- telegrinder/bot/cute_types/pre_checkout_query.py +42 -0
- telegrinder/bot/cute_types/update.py +20 -12
- telegrinder/bot/cute_types/utils.py +3 -36
- telegrinder/bot/dispatch/__init__.py +4 -0
- telegrinder/bot/dispatch/abc.py +8 -9
- telegrinder/bot/dispatch/context.py +5 -7
- telegrinder/bot/dispatch/dispatch.py +85 -33
- telegrinder/bot/dispatch/handler/abc.py +5 -6
- telegrinder/bot/dispatch/handler/audio_reply.py +2 -2
- telegrinder/bot/dispatch/handler/base.py +3 -3
- telegrinder/bot/dispatch/handler/document_reply.py +2 -2
- telegrinder/bot/dispatch/handler/func.py +36 -42
- telegrinder/bot/dispatch/handler/media_group_reply.py +5 -4
- telegrinder/bot/dispatch/handler/message_reply.py +2 -2
- telegrinder/bot/dispatch/handler/photo_reply.py +2 -2
- telegrinder/bot/dispatch/handler/sticker_reply.py +2 -2
- telegrinder/bot/dispatch/handler/video_reply.py +2 -2
- telegrinder/bot/dispatch/middleware/abc.py +83 -8
- telegrinder/bot/dispatch/middleware/global_middleware.py +70 -0
- telegrinder/bot/dispatch/process.py +44 -50
- telegrinder/bot/dispatch/return_manager/__init__.py +2 -0
- telegrinder/bot/dispatch/return_manager/abc.py +6 -10
- telegrinder/bot/dispatch/return_manager/pre_checkout_query.py +20 -0
- telegrinder/bot/dispatch/view/__init__.py +2 -0
- telegrinder/bot/dispatch/view/abc.py +10 -6
- telegrinder/bot/dispatch/view/base.py +81 -50
- telegrinder/bot/dispatch/view/box.py +20 -9
- telegrinder/bot/dispatch/view/callback_query.py +3 -4
- telegrinder/bot/dispatch/view/chat_join_request.py +2 -7
- telegrinder/bot/dispatch/view/chat_member.py +3 -5
- telegrinder/bot/dispatch/view/inline_query.py +3 -4
- telegrinder/bot/dispatch/view/message.py +3 -4
- telegrinder/bot/dispatch/view/pre_checkout_query.py +16 -0
- telegrinder/bot/dispatch/view/raw.py +42 -40
- telegrinder/bot/dispatch/waiter_machine/actions.py +5 -4
- telegrinder/bot/dispatch/waiter_machine/hasher/__init__.py +0 -0
- telegrinder/bot/dispatch/waiter_machine/hasher/callback.py +0 -0
- telegrinder/bot/dispatch/waiter_machine/hasher/hasher.py +9 -7
- telegrinder/bot/dispatch/waiter_machine/hasher/message.py +0 -0
- telegrinder/bot/dispatch/waiter_machine/hasher/state.py +3 -2
- telegrinder/bot/dispatch/waiter_machine/machine.py +113 -34
- telegrinder/bot/dispatch/waiter_machine/middleware.py +15 -10
- telegrinder/bot/dispatch/waiter_machine/short_state.py +7 -18
- telegrinder/bot/polling/polling.py +62 -54
- telegrinder/bot/rules/__init__.py +24 -1
- telegrinder/bot/rules/abc.py +17 -10
- telegrinder/bot/rules/callback_data.py +20 -61
- telegrinder/bot/rules/chat_join.py +6 -4
- telegrinder/bot/rules/command.py +4 -4
- telegrinder/bot/rules/enum_text.py +1 -4
- telegrinder/bot/rules/func.py +5 -3
- telegrinder/bot/rules/fuzzy.py +1 -1
- telegrinder/bot/rules/id.py +24 -0
- telegrinder/bot/rules/inline.py +6 -4
- telegrinder/bot/rules/integer.py +2 -1
- telegrinder/bot/rules/logic.py +18 -0
- telegrinder/bot/rules/markup.py +5 -6
- telegrinder/bot/rules/message.py +2 -4
- telegrinder/bot/rules/message_entities.py +1 -3
- telegrinder/bot/rules/node.py +15 -9
- telegrinder/bot/rules/payload.py +81 -0
- telegrinder/bot/rules/payment_invoice.py +29 -0
- telegrinder/bot/rules/regex.py +5 -6
- telegrinder/bot/rules/state.py +1 -3
- telegrinder/bot/rules/text.py +10 -5
- telegrinder/bot/rules/update.py +0 -0
- telegrinder/bot/scenario/abc.py +2 -4
- telegrinder/bot/scenario/checkbox.py +12 -14
- telegrinder/bot/scenario/choice.py +6 -9
- telegrinder/client/__init__.py +9 -1
- telegrinder/client/abc.py +35 -10
- telegrinder/client/aiohttp.py +28 -24
- telegrinder/client/form_data.py +31 -0
- telegrinder/client/sonic.py +212 -0
- telegrinder/model.py +38 -145
- telegrinder/modules.py +3 -1
- telegrinder/msgspec_utils.py +136 -68
- telegrinder/node/__init__.py +74 -13
- telegrinder/node/attachment.py +92 -16
- telegrinder/node/base.py +196 -68
- telegrinder/node/callback_query.py +17 -16
- telegrinder/node/command.py +3 -2
- telegrinder/node/composer.py +40 -75
- telegrinder/node/container.py +13 -7
- telegrinder/node/either.py +82 -0
- telegrinder/node/event.py +20 -31
- telegrinder/node/file.py +51 -0
- telegrinder/node/me.py +4 -5
- telegrinder/node/payload.py +78 -0
- telegrinder/node/polymorphic.py +27 -8
- telegrinder/node/rule.py +2 -6
- telegrinder/node/scope.py +4 -6
- telegrinder/node/source.py +37 -21
- telegrinder/node/text.py +20 -8
- telegrinder/node/tools/generator.py +7 -11
- telegrinder/py.typed +0 -0
- telegrinder/rules.py +0 -61
- telegrinder/tools/__init__.py +97 -38
- telegrinder/tools/adapter/__init__.py +19 -0
- telegrinder/tools/adapter/abc.py +49 -0
- telegrinder/tools/adapter/dataclass.py +56 -0
- telegrinder/{bot/rules → tools}/adapter/event.py +8 -10
- telegrinder/{bot/rules → tools}/adapter/node.py +8 -10
- telegrinder/{bot/rules → tools}/adapter/raw_event.py +2 -2
- telegrinder/{bot/rules → tools}/adapter/raw_update.py +2 -2
- telegrinder/tools/buttons.py +52 -26
- telegrinder/tools/callback_data_serilization/__init__.py +5 -0
- telegrinder/tools/callback_data_serilization/abc.py +51 -0
- telegrinder/tools/callback_data_serilization/json_ser.py +60 -0
- telegrinder/tools/callback_data_serilization/msgpack_ser.py +172 -0
- telegrinder/tools/error_handler/abc.py +4 -7
- telegrinder/tools/error_handler/error.py +0 -0
- telegrinder/tools/error_handler/error_handler.py +34 -48
- telegrinder/tools/formatting/__init__.py +57 -37
- telegrinder/tools/formatting/deep_links.py +541 -0
- telegrinder/tools/formatting/{html.py → html_formatter.py} +51 -79
- telegrinder/tools/formatting/spec_html_formats.py +14 -60
- telegrinder/tools/functional.py +1 -5
- telegrinder/tools/global_context/global_context.py +26 -51
- telegrinder/tools/global_context/telegrinder_ctx.py +3 -3
- telegrinder/tools/i18n/abc.py +0 -0
- telegrinder/tools/i18n/middleware/abc.py +3 -6
- telegrinder/tools/input_file_directory.py +30 -0
- telegrinder/tools/keyboard.py +9 -9
- telegrinder/tools/lifespan.py +105 -0
- telegrinder/tools/limited_dict.py +5 -10
- telegrinder/tools/loop_wrapper/abc.py +7 -2
- telegrinder/tools/loop_wrapper/loop_wrapper.py +40 -95
- telegrinder/tools/magic.py +184 -34
- telegrinder/tools/state_storage/__init__.py +0 -0
- telegrinder/tools/state_storage/abc.py +5 -9
- telegrinder/tools/state_storage/memory.py +1 -1
- telegrinder/tools/strings.py +13 -0
- telegrinder/types/__init__.py +8 -0
- telegrinder/types/enums.py +31 -21
- telegrinder/types/input_file.py +51 -0
- telegrinder/types/methods.py +531 -109
- telegrinder/types/objects.py +934 -826
- telegrinder/verification_utils.py +0 -2
- {telegrinder-0.3.4.post1.dist-info → telegrinder-0.4.0.dist-info}/LICENSE +2 -2
- telegrinder-0.4.0.dist-info/METADATA +144 -0
- telegrinder-0.4.0.dist-info/RECORD +182 -0
- {telegrinder-0.3.4.post1.dist-info → telegrinder-0.4.0.dist-info}/WHEEL +1 -1
- telegrinder/bot/rules/adapter/__init__.py +0 -17
- telegrinder/bot/rules/adapter/abc.py +0 -31
- telegrinder/node/message.py +0 -14
- telegrinder/node/update.py +0 -15
- telegrinder/tools/formatting/links.py +0 -38
- telegrinder/tools/kb_set/__init__.py +0 -4
- telegrinder/tools/kb_set/base.py +0 -15
- telegrinder/tools/kb_set/yaml.py +0 -63
- telegrinder-0.3.4.post1.dist-info/METADATA +0 -110
- telegrinder-0.3.4.post1.dist-info/RECORD +0 -165
- /telegrinder/{bot/rules → tools}/adapter/errors.py +0 -0
telegrinder/msgspec_utils.py
CHANGED
|
@@ -1,48 +1,40 @@
|
|
|
1
|
-
import dataclasses
|
|
2
1
|
import typing
|
|
3
2
|
from contextlib import contextmanager
|
|
4
3
|
|
|
5
4
|
import fntypes.option
|
|
6
5
|
import fntypes.result
|
|
7
6
|
import msgspec
|
|
8
|
-
from fntypes.co import Error, Ok,
|
|
7
|
+
from fntypes.co import Error, Ok, Variative
|
|
9
8
|
|
|
10
9
|
if typing.TYPE_CHECKING:
|
|
11
10
|
from datetime import datetime
|
|
12
11
|
|
|
13
12
|
from fntypes.option import Option
|
|
14
13
|
|
|
15
|
-
def get_class_annotations(obj: typing.Any) -> dict[str,
|
|
14
|
+
def get_class_annotations(obj: typing.Any, /) -> dict[str, typing.Any]: ...
|
|
16
15
|
|
|
17
|
-
def get_type_hints(obj: typing.Any) -> dict[str,
|
|
16
|
+
def get_type_hints(obj: typing.Any, /) -> dict[str, typing.Any]: ...
|
|
18
17
|
|
|
19
18
|
else:
|
|
20
19
|
from datetime import datetime as dt
|
|
21
20
|
|
|
22
21
|
from msgspec._utils import get_class_annotations, get_type_hints
|
|
23
22
|
|
|
24
|
-
Value = typing.TypeVar("Value")
|
|
25
|
-
Err = typing.TypeVar("Err")
|
|
26
|
-
|
|
27
23
|
datetime = type("datetime", (dt,), {})
|
|
28
24
|
|
|
29
25
|
class OptionMeta(type):
|
|
30
26
|
def __instancecheck__(cls, __instance: typing.Any) -> bool:
|
|
31
|
-
return isinstance(__instance, fntypes.option.Some | fntypes.option.Nothing)
|
|
27
|
+
return isinstance(__instance, (fntypes.option.Some | fntypes.option.Nothing, msgspec.UnsetType))
|
|
32
28
|
|
|
33
|
-
class Option
|
|
29
|
+
class Option[Value](metaclass=OptionMeta):
|
|
34
30
|
pass
|
|
35
31
|
|
|
36
32
|
|
|
37
|
-
T = typing.
|
|
38
|
-
|
|
39
|
-
DecHook: typing.TypeAlias = typing.Callable[[type[T], typing.Any], typing.Any]
|
|
40
|
-
EncHook: typing.TypeAlias = typing.Callable[[T], typing.Any]
|
|
33
|
+
type DecHook[T] = typing.Callable[typing.Concatenate[type[T], typing.Any, ...], typing.Any]
|
|
34
|
+
type EncHook[T] = typing.Callable[typing.Concatenate[T, ...], typing.Any]
|
|
41
35
|
|
|
42
|
-
Nothing: typing.Final[fntypes.option.Nothing] = fntypes.option.Nothing()
|
|
43
36
|
|
|
44
|
-
|
|
45
|
-
def get_origin(t: type[T]) -> type[T]:
|
|
37
|
+
def get_origin[T](t: type[T]) -> type[T]:
|
|
46
38
|
return typing.cast(T, typing.get_origin(t)) or t
|
|
47
39
|
|
|
48
40
|
|
|
@@ -60,6 +52,14 @@ def is_common_type(type_: typing.Any) -> typing.TypeGuard[type[typing.Any]]:
|
|
|
60
52
|
)
|
|
61
53
|
|
|
62
54
|
|
|
55
|
+
def struct_as_dict(struct: msgspec.Struct, /) -> dict[str, typing.Any]:
|
|
56
|
+
return {
|
|
57
|
+
k: v
|
|
58
|
+
for k, v in msgspec.structs.asdict(struct).items()
|
|
59
|
+
if not isinstance(v, msgspec.UnsetType | type(None) | fntypes.option.Nothing)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
63
|
def type_check(obj: typing.Any, t: typing.Any) -> bool:
|
|
64
64
|
return (
|
|
65
65
|
isinstance(obj, t)
|
|
@@ -70,7 +70,7 @@ def type_check(obj: typing.Any, t: typing.Any) -> bool:
|
|
|
70
70
|
)
|
|
71
71
|
|
|
72
72
|
|
|
73
|
-
def msgspec_convert(obj: typing.Any, t: type[T]) -> Result[T, str]:
|
|
73
|
+
def msgspec_convert[T](obj: typing.Any, t: type[T]) -> fntypes.result.Result[T, str]:
|
|
74
74
|
try:
|
|
75
75
|
return Ok(decoder.convert(obj, type=t, strict=True))
|
|
76
76
|
except msgspec.ValidationError:
|
|
@@ -95,9 +95,15 @@ def msgspec_to_builtins(
|
|
|
95
95
|
return Error(exc)
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
def option_dec_hook(
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
def option_dec_hook(
|
|
99
|
+
tp: type[Option[typing.Any]],
|
|
100
|
+
obj: typing.Any,
|
|
101
|
+
) -> fntypes.option.Option[typing.Any] | msgspec.UnsetType:
|
|
102
|
+
if obj is msgspec.UNSET:
|
|
103
|
+
return obj
|
|
104
|
+
|
|
105
|
+
if obj is None or isinstance(obj, fntypes.option.Nothing):
|
|
106
|
+
return fntypes.option.Nothing()
|
|
101
107
|
|
|
102
108
|
(value_type,) = typing.get_args(tp) or (typing.Any,)
|
|
103
109
|
orig_value_type = typing.get_origin(value_type) or value_type
|
|
@@ -156,11 +162,6 @@ def variative_dec_hook(tp: type[Variative], obj: typing.Any) -> Variative:
|
|
|
156
162
|
)
|
|
157
163
|
|
|
158
164
|
|
|
159
|
-
@typing.runtime_checkable
|
|
160
|
-
class DataclassInstance(typing.Protocol):
|
|
161
|
-
__dataclass_fields__: typing.ClassVar[dict[str, dataclasses.Field[typing.Any]]]
|
|
162
|
-
|
|
163
|
-
|
|
164
165
|
class Decoder:
|
|
165
166
|
"""Class `Decoder` for `msgspec` module with decode hook
|
|
166
167
|
for objects with the specified type.
|
|
@@ -175,7 +176,7 @@ class Decoder:
|
|
|
175
176
|
TWO = 2
|
|
176
177
|
THREE = 3
|
|
177
178
|
|
|
178
|
-
decoder =
|
|
179
|
+
decoder = Decoder()
|
|
179
180
|
decoder.dec_hooks[dt] = lambda t, timestamp: t.fromtimestamp(timestamp)
|
|
180
181
|
|
|
181
182
|
decoder.dec_hook(dt, 1713354732) #> datetime.datetime(2024, 4, 17, 14, 52, 12)
|
|
@@ -203,17 +204,26 @@ class Decoder:
|
|
|
203
204
|
)
|
|
204
205
|
|
|
205
206
|
@typing.overload
|
|
206
|
-
def __call__
|
|
207
|
+
def __call__[T](
|
|
208
|
+
self,
|
|
209
|
+
type: type[T],
|
|
210
|
+
context: dict[str, typing.Any] | None = None,
|
|
211
|
+
) -> typing.ContextManager[msgspec.json.Decoder[T]]: ...
|
|
207
212
|
|
|
208
213
|
@typing.overload
|
|
209
|
-
def __call__(
|
|
214
|
+
def __call__(
|
|
215
|
+
self,
|
|
216
|
+
type: typing.Any,
|
|
217
|
+
context: dict[str, typing.Any] | None = None,
|
|
218
|
+
) -> typing.ContextManager[msgspec.json.Decoder[typing.Any]]: ...
|
|
210
219
|
|
|
211
220
|
@typing.overload
|
|
212
|
-
def __call__(
|
|
221
|
+
def __call__[T](
|
|
213
222
|
self,
|
|
214
223
|
type: type[T],
|
|
215
224
|
*,
|
|
216
225
|
strict: bool = True,
|
|
226
|
+
context: dict[str, typing.Any] | None = None,
|
|
217
227
|
) -> typing.ContextManager[msgspec.json.Decoder[T]]: ...
|
|
218
228
|
|
|
219
229
|
@typing.overload
|
|
@@ -222,34 +232,41 @@ class Decoder:
|
|
|
222
232
|
type: typing.Any,
|
|
223
233
|
*,
|
|
224
234
|
strict: bool = True,
|
|
235
|
+
context: dict[str, typing.Any] | None = None,
|
|
225
236
|
) -> typing.ContextManager[msgspec.json.Decoder[typing.Any]]: ...
|
|
226
237
|
|
|
227
238
|
@contextmanager
|
|
228
|
-
def __call__(self, type=object, *, strict=True):
|
|
229
|
-
"""Context manager returns
|
|
230
|
-
|
|
239
|
+
def __call__(self, type=object, *, strict=True, context=None):
|
|
240
|
+
"""Context manager returns an `msgspec.json.Decoder` object with the `dec_hook`."""
|
|
231
241
|
dec_obj = msgspec.json.Decoder(
|
|
232
242
|
type=typing.Any if type is object else type,
|
|
233
243
|
strict=strict,
|
|
234
|
-
dec_hook=self.dec_hook,
|
|
244
|
+
dec_hook=self.dec_hook(context),
|
|
235
245
|
)
|
|
236
246
|
yield dec_obj
|
|
237
247
|
|
|
238
|
-
def add_dec_hook(self, t: type[T]):
|
|
248
|
+
def add_dec_hook[T](self, t: type[T], /):
|
|
239
249
|
def decorator(func: DecHook[T]) -> DecHook[T]:
|
|
240
|
-
return self.dec_hooks.setdefault(get_origin(t), func)
|
|
250
|
+
return self.dec_hooks.setdefault(get_origin(t), func)
|
|
241
251
|
|
|
242
252
|
return decorator
|
|
243
253
|
|
|
244
|
-
def dec_hook(self,
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
254
|
+
def dec_hook(self, context: dict[str, typing.Any] | None = None):
|
|
255
|
+
from telegrinder.tools.magic import magic_bundle
|
|
256
|
+
|
|
257
|
+
def inner(tp: type[typing.Any], obj: object) -> typing.Any:
|
|
258
|
+
origin_type = t if isinstance((t := get_origin(tp)), type) else type(t)
|
|
259
|
+
if origin_type not in self.dec_hooks:
|
|
260
|
+
raise TypeError(
|
|
261
|
+
f"Unknown type `{repr_type(origin_type)}`. You can implement decode hook for this type."
|
|
262
|
+
)
|
|
263
|
+
dec_hook_func = self.dec_hooks[origin_type]
|
|
264
|
+
kwargs = magic_bundle(dec_hook_func, context or {}, start_idx=2, bundle_ctx=False)
|
|
265
|
+
return dec_hook_func(tp, obj, **kwargs)
|
|
266
|
+
|
|
267
|
+
return inner
|
|
251
268
|
|
|
252
|
-
def convert(
|
|
269
|
+
def convert[T](
|
|
253
270
|
self,
|
|
254
271
|
obj: object,
|
|
255
272
|
*,
|
|
@@ -258,33 +275,52 @@ class Decoder:
|
|
|
258
275
|
from_attributes: bool = False,
|
|
259
276
|
builtin_types: typing.Iterable[type[typing.Any]] | None = None,
|
|
260
277
|
str_keys: bool = False,
|
|
278
|
+
context: dict[str, typing.Any] | None = None,
|
|
261
279
|
) -> T:
|
|
262
280
|
return msgspec.convert(
|
|
263
281
|
obj,
|
|
264
282
|
type,
|
|
265
283
|
strict=strict,
|
|
266
284
|
from_attributes=from_attributes,
|
|
267
|
-
dec_hook=self.dec_hook,
|
|
285
|
+
dec_hook=self.dec_hook(context),
|
|
268
286
|
builtin_types=builtin_types,
|
|
269
287
|
str_keys=str_keys,
|
|
270
288
|
)
|
|
271
289
|
|
|
272
290
|
@typing.overload
|
|
273
|
-
def decode(
|
|
291
|
+
def decode(
|
|
292
|
+
self,
|
|
293
|
+
buf: str | bytes,
|
|
294
|
+
*,
|
|
295
|
+
context: dict[str, typing.Any] | None = None,
|
|
296
|
+
) -> typing.Any: ...
|
|
274
297
|
|
|
275
298
|
@typing.overload
|
|
276
|
-
def decode
|
|
299
|
+
def decode[T](
|
|
300
|
+
self,
|
|
301
|
+
buf: str | bytes,
|
|
302
|
+
*,
|
|
303
|
+
type: type[T],
|
|
304
|
+
context: dict[str, typing.Any] | None = None,
|
|
305
|
+
) -> T: ...
|
|
277
306
|
|
|
278
307
|
@typing.overload
|
|
279
|
-
def decode(
|
|
308
|
+
def decode(
|
|
309
|
+
self,
|
|
310
|
+
buf: str | bytes,
|
|
311
|
+
*,
|
|
312
|
+
type: typing.Any,
|
|
313
|
+
context: dict[str, typing.Any] | None = None,
|
|
314
|
+
) -> typing.Any: ...
|
|
280
315
|
|
|
281
316
|
@typing.overload
|
|
282
|
-
def decode(
|
|
317
|
+
def decode[T](
|
|
283
318
|
self,
|
|
284
319
|
buf: str | bytes,
|
|
285
320
|
*,
|
|
286
321
|
type: type[T],
|
|
287
322
|
strict: bool = True,
|
|
323
|
+
context: dict[str, typing.Any] | None = None,
|
|
288
324
|
) -> T: ...
|
|
289
325
|
|
|
290
326
|
@typing.overload
|
|
@@ -294,14 +330,15 @@ class Decoder:
|
|
|
294
330
|
*,
|
|
295
331
|
type: typing.Any,
|
|
296
332
|
strict: bool = True,
|
|
333
|
+
context: dict[str, typing.Any] | None = None,
|
|
297
334
|
) -> typing.Any: ...
|
|
298
335
|
|
|
299
|
-
def decode(self, buf, *, type=object, strict=True):
|
|
336
|
+
def decode(self, buf, *, type=object, strict=True, context=None):
|
|
300
337
|
return msgspec.json.decode(
|
|
301
338
|
buf,
|
|
302
339
|
type=typing.Any if type is object else type,
|
|
303
340
|
strict=strict,
|
|
304
|
-
dec_hook=self.dec_hook,
|
|
341
|
+
dec_hook=self.dec_hook(context),
|
|
305
342
|
)
|
|
306
343
|
|
|
307
344
|
|
|
@@ -340,38 +377,68 @@ class Encoder:
|
|
|
340
377
|
decimal_format: typing.Literal["string", "number"] = "string",
|
|
341
378
|
uuid_format: typing.Literal["canonical", "hex"] = "canonical",
|
|
342
379
|
order: typing.Literal[None, "deterministic", "sorted"] = None,
|
|
380
|
+
context: dict[str, typing.Any] | None = None,
|
|
343
381
|
) -> typing.Generator[msgspec.json.Encoder, typing.Any, None]:
|
|
344
|
-
"""Context manager returns
|
|
345
|
-
|
|
346
|
-
enc_obj = msgspec.json.Encoder(enc_hook=self.enc_hook)
|
|
382
|
+
"""Context manager returns an `msgspec.json.Encoder` object with the `enc_hook`."""
|
|
383
|
+
enc_obj = msgspec.json.Encoder(enc_hook=self.enc_hook(context))
|
|
347
384
|
yield enc_obj
|
|
348
385
|
|
|
349
|
-
def add_enc_hook(self, t: type[T]):
|
|
386
|
+
def add_enc_hook[T](self, t: type[T], /):
|
|
350
387
|
def decorator(func: EncHook[T]) -> EncHook[T]:
|
|
351
388
|
encode_hook = self.enc_hooks.setdefault(get_origin(t), func)
|
|
352
389
|
return func if encode_hook is not func else encode_hook
|
|
353
390
|
|
|
354
391
|
return decorator
|
|
355
392
|
|
|
356
|
-
def enc_hook(self,
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
393
|
+
def enc_hook(self, context: dict[str, typing.Any] | None = None):
|
|
394
|
+
from telegrinder.tools.magic import magic_bundle
|
|
395
|
+
|
|
396
|
+
def inner(obj: typing.Any) -> typing.Any:
|
|
397
|
+
origin_type = get_origin(obj.__class__)
|
|
398
|
+
if origin_type not in self.enc_hooks:
|
|
399
|
+
raise NotImplementedError(
|
|
400
|
+
f"Not implemented encode hook for object of type `{repr_type(origin_type)}`.",
|
|
401
|
+
)
|
|
402
|
+
enc_hook_func = self.enc_hooks[origin_type]
|
|
403
|
+
kwargs = magic_bundle(enc_hook_func, context or {}, start_idx=1, bundle_ctx=False)
|
|
404
|
+
return enc_hook_func(obj, **kwargs)
|
|
405
|
+
|
|
406
|
+
return inner
|
|
363
407
|
|
|
364
408
|
@typing.overload
|
|
365
|
-
def encode(
|
|
409
|
+
def encode(
|
|
410
|
+
self,
|
|
411
|
+
obj: typing.Any,
|
|
412
|
+
*,
|
|
413
|
+
context: dict[str, typing.Any] | None = None,
|
|
414
|
+
) -> str: ...
|
|
366
415
|
|
|
367
416
|
@typing.overload
|
|
368
|
-
def encode(
|
|
417
|
+
def encode(
|
|
418
|
+
self,
|
|
419
|
+
obj: typing.Any,
|
|
420
|
+
*,
|
|
421
|
+
as_str: typing.Literal[True],
|
|
422
|
+
context: dict[str, typing.Any] | None = None,
|
|
423
|
+
) -> str: ...
|
|
369
424
|
|
|
370
425
|
@typing.overload
|
|
371
|
-
def encode(
|
|
426
|
+
def encode(
|
|
427
|
+
self,
|
|
428
|
+
obj: typing.Any,
|
|
429
|
+
*,
|
|
430
|
+
as_str: typing.Literal[False],
|
|
431
|
+
context: dict[str, typing.Any] | None = None,
|
|
432
|
+
) -> bytes: ...
|
|
372
433
|
|
|
373
|
-
def encode(
|
|
374
|
-
|
|
434
|
+
def encode(
|
|
435
|
+
self,
|
|
436
|
+
obj: typing.Any,
|
|
437
|
+
*,
|
|
438
|
+
as_str: bool = True,
|
|
439
|
+
context: dict[str, typing.Any] | None = None,
|
|
440
|
+
) -> str | bytes:
|
|
441
|
+
buf = msgspec.json.encode(obj, enc_hook=self.enc_hook(context))
|
|
375
442
|
return buf.decode() if as_str else buf
|
|
376
443
|
|
|
377
444
|
def to_builtins(
|
|
@@ -381,12 +448,13 @@ class Encoder:
|
|
|
381
448
|
str_keys: bool = False,
|
|
382
449
|
builtin_types: typing.Iterable[type[typing.Any]] | None = None,
|
|
383
450
|
order: typing.Literal["deterministic", "sorted"] | None = None,
|
|
451
|
+
context: dict[str, typing.Any] | None = None,
|
|
384
452
|
) -> typing.Any:
|
|
385
453
|
return msgspec.to_builtins(
|
|
386
454
|
obj,
|
|
387
455
|
str_keys=str_keys,
|
|
388
456
|
builtin_types=builtin_types,
|
|
389
|
-
enc_hook=self.enc_hook,
|
|
457
|
+
enc_hook=self.enc_hook(context),
|
|
390
458
|
order=order,
|
|
391
459
|
)
|
|
392
460
|
|
|
@@ -398,7 +466,6 @@ encoder: typing.Final[Encoder] = Encoder()
|
|
|
398
466
|
__all__ = (
|
|
399
467
|
"Decoder",
|
|
400
468
|
"Encoder",
|
|
401
|
-
"Nothing",
|
|
402
469
|
"Option",
|
|
403
470
|
"datetime",
|
|
404
471
|
"decoder",
|
|
@@ -407,4 +474,5 @@ __all__ = (
|
|
|
407
474
|
"get_type_hints",
|
|
408
475
|
"msgspec_convert",
|
|
409
476
|
"msgspec_to_builtins",
|
|
477
|
+
"struct_as_dict",
|
|
410
478
|
)
|
telegrinder/node/__init__.py
CHANGED
|
@@ -1,54 +1,113 @@
|
|
|
1
|
-
from .attachment import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
from .attachment import (
|
|
2
|
+
Animation,
|
|
3
|
+
Attachment,
|
|
4
|
+
Audio,
|
|
5
|
+
Document,
|
|
6
|
+
Photo,
|
|
7
|
+
SuccessfulPayment,
|
|
8
|
+
Video,
|
|
9
|
+
VideoNote,
|
|
10
|
+
Voice,
|
|
11
|
+
)
|
|
12
|
+
from .base import (
|
|
13
|
+
Composable,
|
|
14
|
+
ComposeError,
|
|
15
|
+
DataNode,
|
|
16
|
+
FactoryNode,
|
|
17
|
+
GlobalNode,
|
|
18
|
+
IsNode,
|
|
19
|
+
Name,
|
|
20
|
+
Node,
|
|
21
|
+
NodeComposeFunction,
|
|
22
|
+
NodeImpersonation,
|
|
23
|
+
NodeProto,
|
|
24
|
+
NodeType,
|
|
25
|
+
as_node,
|
|
26
|
+
is_node,
|
|
27
|
+
scalar_node,
|
|
28
|
+
unwrap_node,
|
|
29
|
+
)
|
|
30
|
+
from .callback_query import (
|
|
31
|
+
CallbackQueryData,
|
|
32
|
+
CallbackQueryDataJson,
|
|
33
|
+
Field,
|
|
34
|
+
)
|
|
4
35
|
from .command import CommandInfo
|
|
5
|
-
from .composer import
|
|
36
|
+
from .composer import NodeCollection, NodeSession, compose_node, compose_nodes
|
|
6
37
|
from .container import ContainerNode
|
|
38
|
+
from .either import Either, Optional
|
|
7
39
|
from .event import EventNode
|
|
40
|
+
from .file import File, FileId
|
|
8
41
|
from .me import Me
|
|
9
|
-
from .
|
|
42
|
+
from .payload import Payload, PayloadData, PayloadSerializer
|
|
10
43
|
from .polymorphic import Polymorphic, impl
|
|
11
44
|
from .rule import RuleChain
|
|
12
|
-
from .scope import
|
|
13
|
-
|
|
45
|
+
from .scope import (
|
|
46
|
+
GLOBAL,
|
|
47
|
+
PER_CALL,
|
|
48
|
+
PER_EVENT,
|
|
49
|
+
NodeScope,
|
|
50
|
+
global_node,
|
|
51
|
+
per_call,
|
|
52
|
+
per_event,
|
|
53
|
+
)
|
|
54
|
+
from .source import ChatSource, Source, UserId, UserSource
|
|
14
55
|
from .text import Text, TextInteger, TextLiteral
|
|
15
56
|
from .tools import generate_node
|
|
16
|
-
from .update import UpdateNode
|
|
17
57
|
|
|
18
58
|
__all__ = (
|
|
59
|
+
"Animation",
|
|
19
60
|
"Attachment",
|
|
20
61
|
"Audio",
|
|
21
62
|
"CallbackQueryData",
|
|
22
|
-
"
|
|
63
|
+
"CallbackQueryDataJson",
|
|
23
64
|
"ChatSource",
|
|
24
65
|
"CommandInfo",
|
|
66
|
+
"Composable",
|
|
25
67
|
"ComposeError",
|
|
26
|
-
"Composition",
|
|
27
68
|
"ContainerNode",
|
|
28
69
|
"DataNode",
|
|
70
|
+
"Document",
|
|
71
|
+
"Either",
|
|
29
72
|
"EventNode",
|
|
73
|
+
"FactoryNode",
|
|
74
|
+
"Field",
|
|
30
75
|
"Field",
|
|
76
|
+
"File",
|
|
77
|
+
"FileId",
|
|
31
78
|
"GLOBAL",
|
|
79
|
+
"GlobalNode",
|
|
80
|
+
"IsNode",
|
|
32
81
|
"Me",
|
|
33
|
-
"MessageNode",
|
|
34
82
|
"Name",
|
|
35
83
|
"Node",
|
|
36
84
|
"NodeCollection",
|
|
85
|
+
"NodeComposeFunction",
|
|
86
|
+
"NodeImpersonation",
|
|
87
|
+
"NodeProto",
|
|
37
88
|
"NodeScope",
|
|
38
89
|
"NodeSession",
|
|
90
|
+
"NodeType",
|
|
91
|
+
"Optional",
|
|
39
92
|
"PER_CALL",
|
|
40
93
|
"PER_EVENT",
|
|
94
|
+
"Payload",
|
|
95
|
+
"PayloadData",
|
|
96
|
+
"PayloadSerializer",
|
|
41
97
|
"Photo",
|
|
42
98
|
"Polymorphic",
|
|
43
99
|
"RuleChain",
|
|
44
|
-
"ScalarNode",
|
|
45
100
|
"Source",
|
|
101
|
+
"SuccessfulPayment",
|
|
46
102
|
"Text",
|
|
47
103
|
"TextInteger",
|
|
48
104
|
"TextLiteral",
|
|
49
|
-
"
|
|
105
|
+
"UserId",
|
|
50
106
|
"UserSource",
|
|
51
107
|
"Video",
|
|
108
|
+
"VideoNote",
|
|
109
|
+
"Voice",
|
|
110
|
+
"as_node",
|
|
52
111
|
"compose_node",
|
|
53
112
|
"compose_nodes",
|
|
54
113
|
"generate_node",
|
|
@@ -57,4 +116,6 @@ __all__ = (
|
|
|
57
116
|
"is_node",
|
|
58
117
|
"per_call",
|
|
59
118
|
"per_event",
|
|
119
|
+
"scalar_node",
|
|
120
|
+
"unwrap_node",
|
|
60
121
|
)
|