telegrinder 0.1.dev159__py3-none-any.whl → 0.1.dev161__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 (127) hide show
  1. telegrinder/__init__.py +4 -2
  2. telegrinder/api/__init__.py +0 -0
  3. telegrinder/api/abc.py +5 -0
  4. telegrinder/api/api.py +4 -4
  5. telegrinder/api/error.py +0 -0
  6. telegrinder/api/response.py +0 -0
  7. telegrinder/bot/__init__.py +0 -0
  8. telegrinder/bot/bot.py +0 -0
  9. telegrinder/bot/cute_types/__init__.py +0 -0
  10. telegrinder/bot/cute_types/base.py +0 -0
  11. telegrinder/bot/cute_types/callback_query.py +81 -85
  12. telegrinder/bot/cute_types/inline_query.py +36 -9
  13. telegrinder/bot/cute_types/message.py +524 -568
  14. telegrinder/bot/cute_types/update.py +0 -0
  15. telegrinder/bot/cute_types/utils.py +201 -453
  16. telegrinder/bot/dispatch/__init__.py +0 -0
  17. telegrinder/bot/dispatch/abc.py +0 -0
  18. telegrinder/bot/dispatch/composition.py +0 -0
  19. telegrinder/bot/dispatch/context.py +0 -0
  20. telegrinder/bot/dispatch/dispatch.py +0 -0
  21. telegrinder/bot/dispatch/handler/__init__.py +0 -0
  22. telegrinder/bot/dispatch/handler/abc.py +0 -0
  23. telegrinder/bot/dispatch/handler/func.py +1 -1
  24. telegrinder/bot/dispatch/handler/message_reply.py +0 -0
  25. telegrinder/bot/dispatch/middleware/__init__.py +0 -0
  26. telegrinder/bot/dispatch/middleware/abc.py +0 -0
  27. telegrinder/bot/dispatch/process.py +0 -0
  28. telegrinder/bot/dispatch/return_manager/__init__.py +0 -0
  29. telegrinder/bot/dispatch/return_manager/abc.py +0 -0
  30. telegrinder/bot/dispatch/return_manager/callback_query.py +0 -0
  31. telegrinder/bot/dispatch/return_manager/inline_query.py +0 -0
  32. telegrinder/bot/dispatch/return_manager/message.py +0 -0
  33. telegrinder/bot/dispatch/view/__init__.py +0 -0
  34. telegrinder/bot/dispatch/view/abc.py +20 -16
  35. telegrinder/bot/dispatch/view/box.py +0 -0
  36. telegrinder/bot/dispatch/view/callback_query.py +0 -0
  37. telegrinder/bot/dispatch/view/inline_query.py +0 -0
  38. telegrinder/bot/dispatch/view/message.py +0 -0
  39. telegrinder/bot/dispatch/waiter_machine/__init__.py +0 -0
  40. telegrinder/bot/dispatch/waiter_machine/machine.py +0 -0
  41. telegrinder/bot/dispatch/waiter_machine/middleware.py +0 -0
  42. telegrinder/bot/dispatch/waiter_machine/short_state.py +0 -0
  43. telegrinder/bot/polling/__init__.py +0 -0
  44. telegrinder/bot/polling/abc.py +0 -0
  45. telegrinder/bot/polling/polling.py +7 -11
  46. telegrinder/bot/rules/__init__.py +0 -0
  47. telegrinder/bot/rules/abc.py +1 -1
  48. telegrinder/bot/rules/adapter/__init__.py +0 -0
  49. telegrinder/bot/rules/adapter/abc.py +0 -0
  50. telegrinder/bot/rules/adapter/errors.py +0 -0
  51. telegrinder/bot/rules/adapter/event.py +0 -0
  52. telegrinder/bot/rules/adapter/raw_update.py +0 -0
  53. telegrinder/bot/rules/callback_data.py +3 -11
  54. telegrinder/bot/rules/command.py +0 -0
  55. telegrinder/bot/rules/enum_text.py +0 -0
  56. telegrinder/bot/rules/func.py +0 -0
  57. telegrinder/bot/rules/fuzzy.py +0 -0
  58. telegrinder/bot/rules/inline.py +2 -1
  59. telegrinder/bot/rules/integer.py +0 -0
  60. telegrinder/bot/rules/is_from.py +0 -0
  61. telegrinder/bot/rules/markup.py +3 -1
  62. telegrinder/bot/rules/mention.py +0 -0
  63. telegrinder/bot/rules/message_entities.py +3 -1
  64. telegrinder/bot/rules/regex.py +1 -1
  65. telegrinder/bot/rules/rule_enum.py +0 -0
  66. telegrinder/bot/rules/start.py +0 -0
  67. telegrinder/bot/rules/text.py +0 -0
  68. telegrinder/bot/scenario/__init__.py +2 -2
  69. telegrinder/bot/scenario/abc.py +0 -0
  70. telegrinder/bot/scenario/checkbox.py +9 -13
  71. telegrinder/bot/scenario/choice.py +2 -2
  72. telegrinder/client/__init__.py +0 -0
  73. telegrinder/client/abc.py +0 -0
  74. telegrinder/client/aiohttp.py +0 -0
  75. telegrinder/model.py +35 -36
  76. telegrinder/modules.py +21 -11
  77. telegrinder/msgspec_json.py +0 -0
  78. telegrinder/msgspec_utils.py +2 -2
  79. telegrinder/node/__init__.py +0 -0
  80. telegrinder/node/attachment.py +0 -0
  81. telegrinder/node/base.py +0 -0
  82. telegrinder/node/composer.py +0 -0
  83. telegrinder/node/container.py +0 -0
  84. telegrinder/node/message.py +0 -0
  85. telegrinder/node/rule.py +0 -0
  86. telegrinder/node/source.py +0 -0
  87. telegrinder/node/text.py +0 -0
  88. telegrinder/node/tools/__init__.py +0 -0
  89. telegrinder/node/tools/generator.py +0 -0
  90. telegrinder/node/update.py +0 -0
  91. telegrinder/rules.py +0 -0
  92. telegrinder/tools/__init__.py +2 -3
  93. telegrinder/tools/buttons.py +0 -0
  94. telegrinder/tools/error_handler/__init__.py +2 -0
  95. telegrinder/tools/error_handler/abc.py +5 -1
  96. telegrinder/tools/error_handler/error.py +10 -0
  97. telegrinder/tools/error_handler/error_handler.py +100 -81
  98. telegrinder/tools/formatting/__init__.py +0 -0
  99. telegrinder/tools/formatting/html.py +0 -0
  100. telegrinder/tools/formatting/links.py +0 -0
  101. telegrinder/tools/formatting/spec_html_formats.py +0 -0
  102. telegrinder/tools/global_context/__init__.py +0 -0
  103. telegrinder/tools/global_context/abc.py +0 -0
  104. telegrinder/tools/global_context/global_context.py +65 -67
  105. telegrinder/tools/global_context/telegrinder_ctx.py +0 -0
  106. telegrinder/tools/i18n/__init__.py +0 -0
  107. telegrinder/tools/i18n/base.py +0 -0
  108. telegrinder/tools/i18n/middleware/__init__.py +0 -0
  109. telegrinder/tools/i18n/middleware/base.py +0 -0
  110. telegrinder/tools/i18n/simple.py +0 -0
  111. telegrinder/tools/kb_set/__init__.py +0 -0
  112. telegrinder/tools/kb_set/base.py +0 -0
  113. telegrinder/tools/kb_set/yaml.py +3 -3
  114. telegrinder/tools/keyboard.py +17 -26
  115. telegrinder/tools/loop_wrapper/__init__.py +0 -0
  116. telegrinder/tools/loop_wrapper/abc.py +0 -0
  117. telegrinder/tools/loop_wrapper/loop_wrapper.py +0 -0
  118. telegrinder/tools/magic.py +1 -1
  119. telegrinder/tools/parse_mode.py +0 -0
  120. telegrinder/types/__init__.py +0 -0
  121. telegrinder/types/enums.py +2 -0
  122. telegrinder/types/methods.py +477 -526
  123. telegrinder/types/objects.py +209 -97
  124. {telegrinder-0.1.dev159.dist-info → telegrinder-0.1.dev161.dist-info}/LICENSE +0 -0
  125. {telegrinder-0.1.dev159.dist-info → telegrinder-0.1.dev161.dist-info}/METADATA +9 -8
  126. {telegrinder-0.1.dev159.dist-info → telegrinder-0.1.dev161.dist-info}/RECORD +38 -37
  127. {telegrinder-0.1.dev159.dist-info → telegrinder-0.1.dev161.dist-info}/WHEEL +1 -1
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -36,7 +36,7 @@ class FuncHandler(ABCHandler[EventT], typing.Generic[EventT, F, ErrorHandlerT]):
36
36
 
37
37
  @property
38
38
  def on_error(self):
39
- return self.error_handler.catch
39
+ return self.error_handler.register_catcher
40
40
 
41
41
  async def check(self, api: ABCAPI, event: Update, ctx: Context | None = None) -> bool:
42
42
  ctx = ctx or Context()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -18,6 +18,11 @@ from telegrinder.types.objects import Update
18
18
  EventType = typing.TypeVar("EventType", bound=BaseCute)
19
19
  MiddlewareT = typing.TypeVar("MiddlewareT", bound=ABCMiddleware)
20
20
 
21
+ FuncType: typing.TypeAlias = typing.Callable[
22
+ typing.Concatenate[EventType, ...],
23
+ typing.Coroutine[typing.Any, typing.Any, typing.Any],
24
+ ]
25
+
21
26
 
22
27
  class ABCView(ABC):
23
28
  @abstractmethod
@@ -41,7 +46,7 @@ class ABCStateView(ABCView, typing.Generic[EventType]):
41
46
  def __repr__(self) -> str:
42
47
  return "<{!r}: {}>".format(
43
48
  self.__class__.__name__,
44
- ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())
49
+ ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items()),
45
50
  )
46
51
 
47
52
 
@@ -56,10 +61,12 @@ class BaseView(ABCView, typing.Generic[EventType]):
56
61
  for base in cls.__dict__.get("__orig_bases__", ()):
57
62
  if issubclass(typing.get_origin(base) or base, ABCView):
58
63
  for generic_type in typing.get_args(base):
59
- if issubclass(typing.get_origin(generic_type) or generic_type, BaseCute):
64
+ if issubclass(
65
+ typing.get_origin(generic_type) or generic_type, BaseCute
66
+ ):
60
67
  return Some(generic_type)
61
68
  return Nothing()
62
-
69
+
63
70
  @classmethod
64
71
  def get_raw_event(cls, update: Update) -> Option[Model]:
65
72
  match update.update_type:
@@ -74,13 +81,8 @@ class BaseView(ABCView, typing.Generic[EventType]):
74
81
  is_blocking: bool = True,
75
82
  error_handler: ErrorHandlerT | None = None,
76
83
  ):
77
- def wrapper(
78
- func: typing.Callable[
79
- typing.Concatenate[EventType, ...],
80
- typing.Coroutine,
81
- ]
82
- ):
83
- func_handler = FuncHandler(
84
+ def wrapper(func: FuncType[EventType]):
85
+ func_handler = FuncHandler[EventType, FuncType[EventType], ErrorHandlerT](
84
86
  func,
85
87
  [*self.auto_rules, *rules],
86
88
  is_blocking,
@@ -91,14 +93,14 @@ class BaseView(ABCView, typing.Generic[EventType]):
91
93
  return func_handler
92
94
 
93
95
  return wrapper
94
-
96
+
95
97
  def register_middleware(self, *args: typing.Any, **kwargs: typing.Any):
96
- def wrapper(cls: type[MiddlewareT]):
98
+ def wrapper(cls: type[MiddlewareT]) -> type[MiddlewareT]:
97
99
  self.middlewares.append(cls(*args, **kwargs))
98
100
  return cls
99
-
101
+
100
102
  return wrapper
101
-
103
+
102
104
  async def check(self, event: Update) -> bool:
103
105
  match self.get_raw_event(event):
104
106
  case Some(e) if issubclass(
@@ -110,10 +112,12 @@ class BaseView(ABCView, typing.Generic[EventType]):
110
112
  return True
111
113
  case _:
112
114
  return False
113
-
115
+
114
116
  async def process(self, event: Update, api: ABCAPI) -> bool:
115
117
  return await process_inner(
116
- self.get_event_type().unwrap().from_update(
118
+ self.get_event_type()
119
+ .unwrap()
120
+ .from_update(
117
121
  update=self.get_raw_event(event).unwrap(),
118
122
  bound_api=api,
119
123
  ),
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -71,16 +71,14 @@ class Polling(ABCPolling):
71
71
  async def listen(self) -> typing.AsyncGenerator[list[Update], None]:
72
72
  logger.debug("Listening polling")
73
73
  reconn_counter = 0
74
-
74
+
75
75
  while not self._stop:
76
76
  try:
77
77
  updates = await self.get_updates()
78
78
  reconn_counter = 0
79
79
  if not updates:
80
80
  continue
81
- updates_list: list[Update] = decoder.decode(
82
- updates, type=list[Update]
83
- )
81
+ updates_list: list[Update] = decoder.decode(updates, type=list[Update])
84
82
  if updates_list:
85
83
  yield updates_list
86
84
  self.offset = updates_list[-1].update_id + 1
@@ -100,16 +98,14 @@ class Polling(ABCPolling):
100
98
  self.stop()
101
99
  exit(9)
102
100
  else:
103
- logger.warning("Server disconnected, waiting 5 seconds to reconnetion...")
101
+ logger.warning(
102
+ "Server disconnected, waiting 5 seconds to reconnetion...",
103
+ )
104
104
  reconn_counter += 1
105
105
  await asyncio.sleep(self.reconnection_timeout)
106
106
  except aiohttp.ClientConnectorError:
107
- logger.error(
108
- "Client connection failed, polling stopping! "
109
- "Please, check your internet connection."
110
- )
111
- self.stop()
112
- exit(3)
107
+ logger.error("Client connection failed, attempted to reconnect...")
108
+ await asyncio.sleep(self.reconnection_timeout)
113
109
  except BaseException as e:
114
110
  logger.exception(e)
115
111
 
File without changes
@@ -19,7 +19,7 @@ Update: typing.TypeAlias = UpdateCute
19
19
  def with_caching_translations(func):
20
20
  """Should be used as decorator for .translate method. Caches rule translations."""
21
21
 
22
- async def wrapper(self: "ABCRule", translator: ABCTranslator):
22
+ async def wrapper(self: "ABCRule[typing.Any]", translator: ABCTranslator):
23
23
  if translation := get_cached_translation(self, translator.locale):
24
24
  return translation
25
25
  translation = await func(self, translator)
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -14,18 +14,10 @@ from telegrinder.tools.buttons import DataclassInstance
14
14
  from .abc import ABCRule
15
15
  from .markup import Markup, PatternLike, check_string
16
16
 
17
- if typing.TYPE_CHECKING:
17
+ T = typing.TypeVar("T")
18
18
 
19
- T = typing.TypeVar("T")
20
- Ref: typing.TypeAlias = typing.Annotated[T, ...]
21
- else:
22
-
23
- class Ref:
24
- def __class_getitem__(cls, code: str) -> typing.ForwardRef:
25
- return typing.ForwardRef(code)
26
-
27
-
28
- CallbackQuery = CallbackQueryCute
19
+ Ref: typing.TypeAlias = typing.Annotated[T, ...]
20
+ CallbackQuery: typing.TypeAlias = CallbackQueryCute
29
21
  Validator: typing.TypeAlias = typing.Callable[[typing.Any], bool | typing.Awaitable[bool]]
30
22
  MapDict: typing.TypeAlias = dict[
31
23
  str, typing.Any | type[typing.Any] | Validator | list[Ref["MapDict"]] | Ref["MapDict"]
File without changes
File without changes
File without changes
File without changes
@@ -1,4 +1,5 @@
1
1
  import abc
2
+ import typing
2
3
 
3
4
  from telegrinder.bot.cute_types import InlineQueryCute
4
5
  from telegrinder.bot.dispatch.context import Context
@@ -8,7 +9,7 @@ from telegrinder.types.enums import ChatType
8
9
 
9
10
  from .markup import Markup, PatternLike, check_string
10
11
 
11
- InlineQuery = InlineQueryCute
12
+ InlineQuery: typing.TypeAlias = InlineQueryCute
12
13
 
13
14
 
14
15
  class InlineQueryRule(ABCRule[InlineQuery], abc.ABC):
File without changes
File without changes
@@ -1,3 +1,5 @@
1
+ import typing
2
+
1
3
  import vbml
2
4
 
3
5
  from telegrinder.bot.dispatch.context import Context
@@ -6,7 +8,7 @@ from telegrinder.tools.global_context import TelegrinderCtx
6
8
  from .abc import Message
7
9
  from .text import TextMessageRule
8
10
 
9
- PatternLike = str | vbml.Pattern
11
+ PatternLike: typing.TypeAlias = str | vbml.Pattern
10
12
  global_ctx = TelegrinderCtx()
11
13
 
12
14
 
File without changes
@@ -1,10 +1,12 @@
1
+ import typing
2
+
1
3
  from telegrinder.bot.dispatch.context import Context
2
4
  from telegrinder.types.enums import MessageEntityType
3
5
  from telegrinder.types.objects import MessageEntity
4
6
 
5
7
  from .abc import Message, MessageRule
6
8
 
7
- Entity = str | MessageEntityType
9
+ Entity: typing.TypeAlias = str | MessageEntityType
8
10
 
9
11
 
10
12
  class HasEntities(MessageRule):
@@ -6,7 +6,7 @@ from telegrinder.bot.dispatch.context import Context
6
6
  from .abc import Message
7
7
  from .text import TextMessageRule
8
8
 
9
- PatternLike = str | typing.Pattern[str]
9
+ PatternLike: typing.TypeAlias = str | typing.Pattern[str]
10
10
 
11
11
 
12
12
  class Regex(TextMessageRule):
File without changes
File without changes
File without changes
@@ -1,5 +1,5 @@
1
1
  from .abc import ABCScenario
2
- from .checkbox import Checkbox
2
+ from .checkbox import Checkbox, Choice
3
3
  from .choice import SingleChoice
4
4
 
5
- __all__ = ("ABCScenario", "Checkbox", "SingleChoice")
5
+ __all__ = ("ABCScenario", "Checkbox", "Choice", "SingleChoice")
File without changes
@@ -1,6 +1,5 @@
1
1
  import dataclasses
2
- import random
3
- import string
2
+ import secrets
4
3
  import typing
5
4
 
6
5
  from telegrinder.bot.cute_types import CallbackQueryCute
@@ -25,29 +24,26 @@ class Choice:
25
24
  code: str
26
25
 
27
26
 
28
- def random_code(length: int) -> str:
29
- return "".join(random.choices(string.ascii_letters + string.digits, k=length))
30
-
31
-
32
27
  class Checkbox(ABCScenario[CallbackQueryCute]):
33
- INVALID_CODE: typing.ClassVar[str] = "Invalid code"
34
- CALLBACK_ANSWER: typing.ClassVar[str] = "Done"
35
- PARSE_MODE: typing.ClassVar[str] = ParseMode.MARKDOWNV2
28
+ INVALID_CODE = "Invalid code"
29
+ CALLBACK_ANSWER = "Done"
30
+ PARSE_MODE = ParseMode.HTML
36
31
 
37
32
  def __init__(
38
33
  self,
39
34
  waiter_machine: WaiterMachine,
40
35
  chat_id: int,
41
36
  msg: str,
37
+ *,
42
38
  ready_text: str = "Ready",
43
39
  max_in_row: int = 3,
44
- ):
40
+ ) -> None:
45
41
  self.chat_id = chat_id
46
42
  self.msg = msg
47
43
  self.choices: list[Choice] = []
48
44
  self.ready = ready_text
49
45
  self.max_in_row = max_in_row
50
- self.random_code = random_code(16)
46
+ self.random_code = secrets.token_hex(16)
51
47
  self.waiter_machine = waiter_machine
52
48
 
53
49
  def get_markup(self) -> InlineKeyboardMarkup:
@@ -77,7 +73,7 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
77
73
  is_picked: bool = False,
78
74
  ) -> typing.Self:
79
75
  self.choices.append(
80
- Choice(name, is_picked, default_text, picked_text, random_code(16)),
76
+ Choice(name, is_picked, default_text, picked_text, secrets.token_hex(16)),
81
77
  )
82
78
  return self
83
79
 
@@ -128,4 +124,4 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
128
124
  )
129
125
 
130
126
 
131
- __all__ = ("Checkbox", "Choice", "random_code")
127
+ __all__ = ("Checkbox", "Choice")
@@ -34,11 +34,11 @@ class SingleChoice(Checkbox):
34
34
  async def wait(
35
35
  self,
36
36
  api: "API",
37
- cb_view: "BaseStateView[CallbackQueryCute]",
37
+ view: "BaseStateView[CallbackQueryCute]",
38
38
  ) -> tuple[str, int]:
39
39
  if len([choice for choice in self.choices if choice.is_picked]) != 1:
40
40
  raise ValueError("Exactly one choice must be picked")
41
- choices, m_id = await super().wait(api, cb_view)
41
+ choices, m_id = await super().wait(api, view)
42
42
  return list(choices.keys())[list(choices.values()).index(True)], m_id
43
43
 
44
44
 
File without changes
telegrinder/client/abc.py CHANGED
File without changes
File without changes
telegrinder/model.py CHANGED
@@ -47,7 +47,7 @@ def full_result(
47
47
 
48
48
  def get_params(params: dict[str, typing.Any]) -> dict[str, typing.Any]:
49
49
  return {
50
- k: v.unwrap() if v and isinstance(v, Some) else v
50
+ k: v.unwrap() if isinstance(v, Some) else v
51
51
  for k, v in (
52
52
  *params.pop("other", {}).items(),
53
53
  *params.items(),
@@ -77,63 +77,62 @@ class DataConverter:
77
77
  files: dict[str, tuple[str, bytes]] = dataclasses.field(default_factory=lambda: {})
78
78
 
79
79
  @property
80
- def converters(self) -> dict[
81
- type[typing.Any], typing.Callable[[typing.Self, typing.Any, bool], typing.Any]
82
- ]:
80
+ def converters(self) -> dict[type[typing.Any], typing.Callable[..., typing.Any]]:
83
81
  return {
84
- get_origin(value.__annotations__["d"]): value
82
+ get_origin(value.__annotations__["data"]): value
85
83
  for key, value in vars(self.__class__).items()
86
- if key.startswith("convert_")
87
- and callable(value)
84
+ if key.startswith("convert_") and callable(value)
88
85
  }
86
+
87
+ @staticmethod
88
+ def convert_enum(data: enum.Enum, _: bool = True) -> typing.Any:
89
+ return data.value
90
+
91
+ @staticmethod
92
+ def convert_datetime(data: datetime, _: bool = True) -> int:
93
+ return int(data.timestamp())
94
+
95
+ def __call__(self, data: typing.Any, *, serialize: bool = True) -> typing.Any:
96
+ converter = self.get_converter(get_origin(type(data)))
97
+ if converter is not None:
98
+ if isinstance(converter, staticmethod):
99
+ return converter(data, serialize)
100
+ return converter(self, data, serialize)
101
+ return data
89
102
 
90
- def get_converter(
91
- self, t: type[typing.Any]
92
- ) -> typing.Callable[[typing.Self, typing.Any, bool], typing.Any] | None:
103
+ def get_converter(self, t: type[typing.Any]):
93
104
  for type, converter in self.converters.items():
94
105
  if issubclass(t, type):
95
106
  return converter
96
107
  return None
97
108
 
98
- def convert_model(self, d: Model, serialize: bool = True) -> str | dict[str, typing.Any]:
99
- converted_dct = self.convert(d.to_dict(), serialize=False)
109
+ def convert_model(self, data: Model, serialize: bool = True) -> str | dict[str, typing.Any]:
110
+ converted_dct = self(data.to_dict(), serialize=False)
100
111
  return encoder.encode(converted_dct) if serialize is True else converted_dct
101
112
 
102
- def convert_dct(self, d: dict[str, typing.Any], serialize: bool = True) -> dict[str, typing.Any]:
113
+ def convert_dct(self, data: dict[str, typing.Any], serialize: bool = True) -> dict[str, typing.Any]:
103
114
  return {
104
- k: self.convert(v, serialize=serialize)
105
- for k, v in d.items()
115
+ k: self(v, serialize=serialize)
116
+ for k, v in data.items()
106
117
  if type(v) not in (NoneType, Nothing)
107
118
  }
108
119
 
109
- def convert_lst(self, d: list[typing.Any], serialize: bool = True) -> str | list[typing.Any]:
110
- converted_lst = [self.convert(x, serialize=False) for x in d]
120
+ def convert_lst(self, data: list[typing.Any], serialize: bool = True) -> str | list[typing.Any]:
121
+ converted_lst = [self(x, serialize=False) for x in data]
111
122
  return encoder.encode(converted_lst) if serialize is True else converted_lst
112
123
 
113
- def convert_tpl(self, d: tuple[typing.Any, ...], serialize: bool = True) -> str | tuple[typing.Any, ...]:
124
+ def convert_tpl(self, data: tuple[typing.Any, ...], _: bool = True) -> str | tuple[typing.Any, ...]:
114
125
  if (
115
- isinstance(d, tuple)
116
- and len(d) == 2
117
- and isinstance(d[0], str)
118
- and isinstance(d[1], bytes)
126
+ isinstance(data, tuple)
127
+ and len(data) == 2
128
+ and isinstance(data[0], str)
129
+ and isinstance(data[1], bytes)
119
130
  ):
120
131
  attach_name = secrets.token_urlsafe(16)
121
- self.files[attach_name] = d
132
+ self.files[attach_name] = data
122
133
  return "attach://{}".format(attach_name)
123
- return d
124
-
125
- def convert_enum(self, d: enum.Enum, serialize: bool = True) -> str:
126
- return d.value
127
-
128
- def convert_datetime(self, d: datetime, serialize: bool = True) -> int:
129
- return int(d.timestamp())
130
-
131
- def convert(self, data: typing.Any, *, serialize: bool = True) -> typing.Any:
132
- converter = self.get_converter(get_origin(type(data)))
133
- if converter is not None:
134
- return converter(self, data, serialize)
135
134
  return data
136
-
135
+
137
136
 
138
137
  __all__ = (
139
138
  "DataConverter",
telegrinder/modules.py CHANGED
@@ -5,7 +5,7 @@ from choicelib import choice_in_order
5
5
 
6
6
 
7
7
  class JSONModule(typing.Protocol):
8
- def loads(self, s: str) -> dict[str, typing.Any] | list[typing.Any]:
8
+ def loads(self, s: str | bytes) -> dict[str, typing.Any] | list[typing.Any]:
9
9
  ...
10
10
 
11
11
  def dumps(self, o: dict[str, typing.Any] | list[typing.Any]) -> str:
@@ -13,22 +13,22 @@ class JSONModule(typing.Protocol):
13
13
 
14
14
 
15
15
  class LoggerModule(typing.Protocol):
16
- def debug(self, __msg: object, *args: object, **kwargs: object):
16
+ def debug(self, __msg: object, *args: object, **kwargs: object) -> None:
17
17
  ...
18
18
 
19
- def info(self, __msg: object, *args: object, **kwargs: object):
19
+ def info(self, __msg: object, *args: object, **kwargs: object) -> None:
20
20
  ...
21
21
 
22
- def warning(self, __msg: object, *args: object, **kwargs: object):
22
+ def warning(self, __msg: object, *args: object, **kwargs: object) -> None:
23
23
  ...
24
24
 
25
- def error(self, __msg: object, *args: object, **kwargs: object):
25
+ def error(self, __msg: object, *args: object, **kwargs: object) -> None:
26
26
  ...
27
27
 
28
- def critical(self, __msg: object, *args: object, **kwargs: object):
28
+ def critical(self, __msg: object, *args: object, **kwargs: object) -> None:
29
29
  ...
30
30
 
31
- def exception(self, __msg: object, *args: object, **kwargs: object):
31
+ def exception(self, __msg: object, *args: object, **kwargs: object) -> None:
32
32
  ...
33
33
 
34
34
  def set_level(
@@ -187,7 +187,7 @@ elif logging_module == "logging":
187
187
 
188
188
 
189
189
  class LogMessage:
190
- def __init__(self, fmt, args, kwargs):
190
+ def __init__(self, fmt: typing.Any, args: typing.Any, kwargs: typing.Any) -> None:
191
191
  self.fmt = fmt
192
192
  self.args = args
193
193
  self.kwargs = kwargs
@@ -195,17 +195,27 @@ elif logging_module == "logging":
195
195
  def __str__(self) -> str:
196
196
  return self.fmt.format(*self.args, **self.kwargs)
197
197
 
198
+
198
199
  class TelegrinderLoggingStyleAdapter(logging.LoggerAdapter):
199
- def __init__(self, logger, extra=None):
200
+ def __init__(
201
+ self,
202
+ logger: LoggerModule,
203
+ extra: dict[str, typing.Any] | None = None,
204
+ ) -> None:
200
205
  super().__init__(logger, extra or {})
201
206
 
202
- def log(self, level, msg, *args, **kwargs):
207
+ def log(self, level: int, msg: object, *args: object, **kwargs: object) -> None:
203
208
  if self.isEnabledFor(level):
204
209
  kwargs.setdefault("stacklevel", 2)
205
210
  msg, args, kwargs = self.proc(msg, args, kwargs)
206
211
  self.logger._log(level, msg, args, **kwargs)
207
212
 
208
- def proc(self, msg, args, kwargs):
213
+ def proc(
214
+ self,
215
+ msg: object,
216
+ args: tuple[object, ...],
217
+ kwargs: dict[str, object],
218
+ ) -> tuple[LogMessage | object, tuple[object, ...], dict[str, object]]:
209
219
  log_kwargs = {
210
220
  key: kwargs[key]
211
221
  for key in inspect.getfullargspec(self.logger._log).args[1:]
File without changes
@@ -191,11 +191,11 @@ class Encoder:
191
191
  return self.enc_hooks[origin_type](obj)
192
192
 
193
193
  @typing.overload
194
- def encode(self, obj: typing.Any) -> str:
194
+ def encode(self, obj: typing.Any, *, as_str: typing.Literal[True] = True) -> str:
195
195
  ...
196
196
 
197
197
  @typing.overload
198
- def encode(self, obj: typing.Any, *, as_str: bool = False) -> bytes:
198
+ def encode(self, obj: typing.Any, *, as_str: typing.Literal[False] = False) -> bytes:
199
199
  ...
200
200
 
201
201
  def encode(self, obj: typing.Any, *, as_str: bool = True) -> str | bytes:
File without changes
File without changes
telegrinder/node/base.py CHANGED
File without changes
File without changes
File without changes
File without changes
telegrinder/node/rule.py CHANGED
File without changes
File without changes