telegrinder 0.1.dev165__py3-none-any.whl → 0.1.dev166__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 (88) hide show
  1. telegrinder/__init__.py +22 -0
  2. telegrinder/api/abc.py +1 -1
  3. telegrinder/api/api.py +8 -6
  4. telegrinder/api/error.py +2 -3
  5. telegrinder/bot/__init__.py +14 -0
  6. telegrinder/bot/bot.py +5 -3
  7. telegrinder/bot/cute_types/__init__.py +4 -0
  8. telegrinder/bot/cute_types/base.py +22 -13
  9. telegrinder/bot/cute_types/chat_join_request.py +63 -0
  10. telegrinder/bot/cute_types/chat_member_updated.py +244 -0
  11. telegrinder/bot/cute_types/message.py +34 -7
  12. telegrinder/bot/cute_types/update.py +5 -4
  13. telegrinder/bot/cute_types/utils.py +39 -17
  14. telegrinder/bot/dispatch/__init__.py +9 -1
  15. telegrinder/bot/dispatch/composition.py +10 -8
  16. telegrinder/bot/dispatch/context.py +9 -10
  17. telegrinder/bot/dispatch/dispatch.py +29 -19
  18. telegrinder/bot/dispatch/handler/abc.py +1 -0
  19. telegrinder/bot/dispatch/handler/func.py +29 -6
  20. telegrinder/bot/dispatch/handler/message_reply.py +2 -3
  21. telegrinder/bot/dispatch/middleware/abc.py +2 -4
  22. telegrinder/bot/dispatch/process.py +4 -3
  23. telegrinder/bot/dispatch/return_manager/__init__.py +1 -1
  24. telegrinder/bot/dispatch/return_manager/abc.py +33 -21
  25. telegrinder/bot/dispatch/return_manager/callback_query.py +4 -2
  26. telegrinder/bot/dispatch/return_manager/inline_query.py +4 -2
  27. telegrinder/bot/dispatch/return_manager/message.py +12 -6
  28. telegrinder/bot/dispatch/view/__init__.py +8 -2
  29. telegrinder/bot/dispatch/view/abc.py +26 -20
  30. telegrinder/bot/dispatch/view/box.py +72 -1
  31. telegrinder/bot/dispatch/view/callback_query.py +1 -3
  32. telegrinder/bot/dispatch/view/chat_join_request.py +17 -0
  33. telegrinder/bot/dispatch/view/chat_member.py +26 -0
  34. telegrinder/bot/dispatch/view/message.py +23 -1
  35. telegrinder/bot/dispatch/view/raw.py +116 -0
  36. telegrinder/bot/dispatch/waiter_machine/__init__.py +2 -1
  37. telegrinder/bot/dispatch/waiter_machine/machine.py +73 -19
  38. telegrinder/bot/dispatch/waiter_machine/middleware.py +3 -3
  39. telegrinder/bot/dispatch/waiter_machine/short_state.py +6 -3
  40. telegrinder/bot/polling/polling.py +4 -2
  41. telegrinder/bot/rules/__init__.py +20 -12
  42. telegrinder/bot/rules/abc.py +0 -9
  43. telegrinder/bot/rules/adapter/event.py +31 -22
  44. telegrinder/bot/rules/callback_data.py +15 -20
  45. telegrinder/bot/rules/chat_join.py +47 -0
  46. telegrinder/bot/rules/enum_text.py +7 -2
  47. telegrinder/bot/rules/inline.py +3 -3
  48. telegrinder/bot/rules/is_from.py +36 -50
  49. telegrinder/bot/rules/message.py +17 -0
  50. telegrinder/bot/rules/message_entities.py +1 -1
  51. telegrinder/bot/rules/start.py +6 -4
  52. telegrinder/bot/rules/text.py +2 -1
  53. telegrinder/bot/rules/update.py +16 -0
  54. telegrinder/bot/scenario/checkbox.py +9 -7
  55. telegrinder/client/aiohttp.py +4 -4
  56. telegrinder/model.py +33 -19
  57. telegrinder/modules.py +16 -32
  58. telegrinder/msgspec_utils.py +37 -36
  59. telegrinder/node/__init__.py +12 -12
  60. telegrinder/node/attachment.py +15 -5
  61. telegrinder/node/base.py +24 -16
  62. telegrinder/node/composer.py +8 -6
  63. telegrinder/node/container.py +1 -1
  64. telegrinder/node/rule.py +4 -4
  65. telegrinder/node/source.py +4 -2
  66. telegrinder/node/tools/generator.py +1 -1
  67. telegrinder/tools/__init__.py +1 -1
  68. telegrinder/tools/error_handler/abc.py +4 -3
  69. telegrinder/tools/error_handler/error_handler.py +22 -16
  70. telegrinder/tools/formatting/html.py +15 -7
  71. telegrinder/tools/formatting/spec_html_formats.py +1 -1
  72. telegrinder/tools/global_context/abc.py +5 -1
  73. telegrinder/tools/global_context/telegrinder_ctx.py +1 -1
  74. telegrinder/tools/i18n/base.py +4 -3
  75. telegrinder/tools/i18n/simple.py +1 -3
  76. telegrinder/tools/keyboard.py +1 -1
  77. telegrinder/tools/loop_wrapper/loop_wrapper.py +24 -16
  78. telegrinder/tools/magic.py +1 -1
  79. telegrinder/types/__init__.py +206 -0
  80. telegrinder/types/enums.py +34 -0
  81. telegrinder/types/methods.py +52 -47
  82. telegrinder/types/objects.py +531 -88
  83. telegrinder/verification_utils.py +3 -1
  84. {telegrinder-0.1.dev165.dist-info → telegrinder-0.1.dev166.dist-info}/METADATA +1 -1
  85. telegrinder-0.1.dev166.dist-info/RECORD +136 -0
  86. telegrinder-0.1.dev165.dist-info/RECORD +0 -128
  87. {telegrinder-0.1.dev165.dist-info → telegrinder-0.1.dev166.dist-info}/LICENSE +0 -0
  88. {telegrinder-0.1.dev165.dist-info → telegrinder-0.1.dev166.dist-info}/WHEEL +0 -0
@@ -1,24 +1,34 @@
1
1
  import typing
2
2
 
3
+ from fntypes.co import Nothing, Some
4
+
3
5
  from telegrinder.bot.cute_types.base import BaseCute
6
+ from telegrinder.bot.cute_types.update import UpdateCute
4
7
  from telegrinder.bot.dispatch.context import Context
5
8
  from telegrinder.msgspec_utils import Option
6
9
  from telegrinder.types.enums import ChatType, DiceEmoji
7
10
  from telegrinder.types.objects import User
8
11
 
9
- from .abc import ABCRule, Message, MessageRule
12
+ from .abc import ABCRule, Message
13
+ from .message import MessageRule
10
14
 
11
15
  T = typing.TypeVar("T", bound=BaseCute)
12
16
 
13
17
 
18
+ def get_from_user(obj: typing.Any) -> User:
19
+ assert isinstance(obj, FromUserProto)
20
+ return obj.from_.unwrap() if isinstance(obj.from_, Some | Nothing) else obj.from_
21
+
22
+
14
23
  @typing.runtime_checkable
15
24
  class FromUserProto(typing.Protocol):
16
25
  from_: User | Option[User]
17
26
 
18
27
 
19
28
  class HasFrom(ABCRule[T]):
20
- async def check(self, event: T, ctx: Context) -> bool:
21
- return isinstance(event, FromUserProto) and bool(event.from_)
29
+ async def check(self, event: UpdateCute, ctx: Context) -> bool:
30
+ event_model = event.incoming_update.unwrap()
31
+ return isinstance(event_model, FromUserProto) and bool(event_model.from_)
22
32
 
23
33
 
24
34
  class HasDice(MessageRule):
@@ -49,29 +59,30 @@ class IsSticker(MessageRule):
49
59
  return bool(message.sticker)
50
60
 
51
61
 
52
- class IsBot(MessageRule, requires=[HasFrom()]):
53
- async def check(self, message: Message, ctx: Context) -> bool:
54
- return message.from_user.is_bot
62
+ class IsBot(ABCRule[T], requires=[HasFrom()]):
63
+ async def check(self, event: UpdateCute, ctx: Context) -> bool:
64
+ return get_from_user(event.incoming_update.unwrap()).is_bot
55
65
 
56
66
 
57
- class IsUser(MessageRule, requires=[HasFrom()]):
58
- async def check(self, message: Message, ctx: Context) -> bool:
59
- return not message.from_user.is_bot
67
+ class IsUser(ABCRule[T], requires=[HasFrom()]):
68
+ async def check(self, event: UpdateCute, ctx: Context) -> bool:
69
+ return not get_from_user(event.incoming_update.unwrap()).is_bot
60
70
 
61
71
 
62
- class IsPremium(MessageRule, requires=[HasFrom()]):
63
- async def check(self, message: Message, ctx: Context) -> bool:
64
- return message.from_user.is_premium.unwrap_or(False)
72
+ class IsPremium(ABCRule[T], requires=[HasFrom()]):
73
+ async def check(self, event: UpdateCute, ctx: Context) -> bool:
74
+ return get_from_user(event.incoming_update.unwrap()).is_premium.unwrap_or(False)
65
75
 
66
76
 
67
- class IsLanguageCode(MessageRule, requires=[HasFrom()]):
77
+ class IsLanguageCode(ABCRule[T], requires=[HasFrom()]):
68
78
  def __init__(self, lang_codes: str | list[str], /) -> None:
69
79
  self.lang_codes = [lang_codes] if isinstance(lang_codes, str) else lang_codes
70
80
 
71
- async def check(self, message: Message, ctx: Context) -> bool:
72
- if not message.from_user.language_code:
73
- return False
74
- return message.from_user.language_code.unwrap() in self.lang_codes
81
+ async def check(self, event: UpdateCute, ctx: Context) -> bool:
82
+ return (
83
+ get_from_user(event.incoming_update.unwrap())
84
+ .language_code.unwrap_or_none() in self.lang_codes
85
+ )
75
86
 
76
87
 
77
88
  class IsForum(MessageRule):
@@ -79,12 +90,12 @@ class IsForum(MessageRule):
79
90
  return message.chat.is_forum.unwrap_or(False)
80
91
 
81
92
 
82
- class IsUserId(MessageRule, requires=[HasFrom()]):
93
+ class IsUserId(ABCRule[T], requires=[HasFrom()]):
83
94
  def __init__(self, user_ids: int | list[int], /) -> None:
84
95
  self.user_ids = [user_ids] if isinstance(user_ids, int) else user_ids
85
96
 
86
- async def check(self, message: Message, ctx: Context) -> bool:
87
- return message.from_user.id in self.user_ids
97
+ async def check(self, event: UpdateCute, ctx: Context) -> bool:
98
+ return get_from_user(event.incoming_update.unwrap()).id in self.user_ids
88
99
 
89
100
 
90
101
  class IsChatId(MessageRule):
@@ -115,44 +126,19 @@ class IsChat(MessageRule):
115
126
  return message.chat.type in (ChatType.GROUP, ChatType.SUPERGROUP)
116
127
 
117
128
 
118
- class IsDice(MessageRule, requires=[HasDice()]):
119
- async def check(self, message: Message, ctx: Context) -> bool:
120
- return message.dice.unwrap().emoji == DiceEmoji.DICE
121
-
122
-
123
- class IsDartDice(MessageRule, requires=[HasDice()]):
124
- async def check(self, message: Message, ctx: Context) -> bool:
125
- return message.dice.unwrap().emoji == DiceEmoji.DART
126
-
127
-
128
- class IsBasketballDice(MessageRule, requires=[HasDice()]):
129
- async def check(self, message: Message, ctx: Context) -> bool:
130
- return message.dice.unwrap().emoji == DiceEmoji.BASKETBALL
131
-
132
-
133
- class IsFootballDice(MessageRule, requires=[HasDice()]):
134
- async def check(self, message: Message, ctx: Context) -> bool:
135
- return message.dice.unwrap().emoji == DiceEmoji.FOOTBALL
136
-
137
-
138
- class IsSlotMachineDice(MessageRule, requires=[HasDice()]):
139
- async def check(self, message: Message, ctx: Context) -> bool:
140
- return message.dice.unwrap().emoji == DiceEmoji.SLOT_MACHINE
141
-
129
+ class IsDiceEmoji(MessageRule, requires=[HasDice()]):
130
+ def __init__(self, dice_emoji: DiceEmoji, /) -> None:
131
+ self.dice_emoji = dice_emoji
142
132
 
143
- class IsBowlingDice(MessageRule, requires=[HasDice()]):
144
133
  async def check(self, message: Message, ctx: Context) -> bool:
145
- return message.dice.unwrap().emoji == DiceEmoji.BOWLING
134
+ return message.dice.unwrap().emoji == self.dice_emoji
146
135
 
147
136
 
148
137
  __all__ = (
149
- "IsBasketballDice",
150
138
  "IsBot",
151
- "IsBowlingDice",
152
139
  "IsChat",
153
140
  "IsChatId",
154
- "IsDartDice",
155
- "IsDice",
141
+ "IsDiceEmoji",
156
142
  "IsForum",
157
143
  "IsForward",
158
144
  "IsForwardType",
@@ -0,0 +1,17 @@
1
+ import abc
2
+
3
+ from telegrinder.bot.dispatch.context import Context
4
+ from telegrinder.types.objects import Message as MessageEvent
5
+
6
+ from .abc import ABCRule, Message
7
+ from .adapter import EventAdapter
8
+
9
+
10
+ class MessageRule(ABCRule[Message], abc.ABC):
11
+ adapter = EventAdapter(MessageEvent, Message)
12
+
13
+ @abc.abstractmethod
14
+ async def check(self, message: Message, ctx: Context) -> bool: ...
15
+
16
+
17
+ __all__ = ("MessageRule",)
@@ -4,7 +4,7 @@ from telegrinder.bot.dispatch.context import Context
4
4
  from telegrinder.types.enums import MessageEntityType
5
5
  from telegrinder.types.objects import MessageEntity
6
6
 
7
- from .abc import Message, MessageRule
7
+ from .message import Message, MessageRule
8
8
 
9
9
  Entity: typing.TypeAlias = str | MessageEntityType
10
10
 
@@ -3,17 +3,19 @@ import typing
3
3
  from telegrinder.bot.dispatch.context import Context
4
4
  from telegrinder.types.enums import MessageEntityType
5
5
 
6
- from .abc import MessageRule
7
6
  from .is_from import IsPrivate
8
7
  from .markup import Markup, Message
8
+ from .message import MessageRule
9
9
  from .message_entities import MessageEntities
10
10
 
11
11
 
12
12
  class StartCommand(
13
- MessageRule, requires=[
14
- IsPrivate() & MessageEntities(MessageEntityType.BOT_COMMAND)
13
+ MessageRule,
14
+ requires=[
15
+ IsPrivate()
16
+ & MessageEntities(MessageEntityType.BOT_COMMAND)
15
17
  & Markup(["/start <param>", "/start"]),
16
- ]
18
+ ],
17
19
  ):
18
20
  def __init__(
19
21
  self,
@@ -1,7 +1,8 @@
1
1
  from telegrinder.bot.dispatch.context import Context
2
2
  from telegrinder.tools.i18n.base import ABCTranslator
3
3
 
4
- from .abc import ABC, Message, MessageRule, with_caching_translations
4
+ from .abc import ABC, Message, with_caching_translations
5
+ from .message import MessageRule
5
6
 
6
7
 
7
8
  class HasText(MessageRule):
@@ -0,0 +1,16 @@
1
+ from telegrinder.bot.cute_types.update import UpdateCute
2
+ from telegrinder.bot.dispatch.context import Context
3
+ from telegrinder.types.enums import UpdateType
4
+
5
+ from .abc import ABCRule, T
6
+
7
+
8
+ class IsUpdate(ABCRule[T]):
9
+ def __init__(self, update_type: UpdateType, /) -> None:
10
+ self.update_type = update_type
11
+
12
+ async def check(self, event: UpdateCute, ctx: Context) -> bool:
13
+ return event.update_type.unwrap_or_none() == self.update_type
14
+
15
+
16
+ __all__ = ("IsUpdate",)
@@ -45,7 +45,7 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
45
45
  self.max_in_row = max_in_row
46
46
  self.random_code = secrets.token_hex(8)
47
47
  self.waiter_machine = waiter_machine
48
-
48
+
49
49
  def __repr__(self) -> str:
50
50
  return (
51
51
  "<{}@{!r}: (choices={!r}, max_in_row={}) with waiter_machine={!r}, ready_text={!r} "
@@ -69,14 +69,16 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
69
69
  choice = choices.pop(0)
70
70
  kb.add(
71
71
  InlineButton(
72
- text=choice.default_text
73
- if not choice.is_picked
74
- else choice.picked_text,
72
+ text=(
73
+ choice.default_text
74
+ if not choice.is_picked
75
+ else choice.picked_text
76
+ ),
75
77
  callback_data=self.random_code + "/" + choice.code,
76
78
  )
77
79
  )
78
80
  kb.row()
79
-
81
+
80
82
  kb.add(InlineButton(self.ready, callback_data=self.random_code + "/ready"))
81
83
  return kb.get_markup()
82
84
 
@@ -125,14 +127,14 @@ class Checkbox(ABCScenario[CallbackQueryCute]):
125
127
  reply_markup=self.get_markup(),
126
128
  )
127
129
  ).unwrap()
128
-
130
+
129
131
  while True:
130
132
  q, _ = await self.waiter_machine.wait(view, (api, message.message_id))
131
133
  should_continue = await self.handle(q)
132
134
  await q.answer(self.CALLBACK_ANSWER)
133
135
  if not should_continue:
134
136
  break
135
-
137
+
136
138
  return (
137
139
  {choice.name: choice.is_picked for choice in self.choices},
138
140
  message.message_id,
@@ -24,7 +24,7 @@ class AiohttpClient(ABCClient):
24
24
  self.json_processing_module = json_processing_module or json
25
25
  self.session_params = session_params
26
26
  self.timeout = timeout or aiohttp.ClientTimeout(total=0)
27
-
27
+
28
28
  def __repr__(self) -> str:
29
29
  return "<{}: session={!r}, timeout={}, closed={}>".format(
30
30
  self.__class__.__name__,
@@ -32,7 +32,7 @@ class AiohttpClient(ABCClient):
32
32
  self.timeout,
33
33
  True if self.session is None else self.session.closed,
34
34
  )
35
-
35
+
36
36
  async def request_raw(
37
37
  self,
38
38
  url: str,
@@ -118,10 +118,10 @@ class AiohttpClient(ABCClient):
118
118
  form = aiohttp.formdata.FormData(quote_fields=False)
119
119
  for k, v in data.items():
120
120
  form.add_field(k, str(v))
121
-
121
+
122
122
  for n, f in files.items():
123
123
  form.add_field(n, f[1], filename=f[0])
124
-
124
+
125
125
  return form
126
126
 
127
127
  def __del__(self) -> None:
telegrinder/model.py CHANGED
@@ -14,7 +14,7 @@ T = typing.TypeVar("T")
14
14
 
15
15
  if typing.TYPE_CHECKING:
16
16
  from telegrinder.api.error import APIError
17
-
17
+
18
18
 
19
19
  MODEL_CONFIG: typing.Final[dict[str, typing.Any]] = {
20
20
  "omit_defaults": True,
@@ -26,16 +26,14 @@ MODEL_CONFIG: typing.Final[dict[str, typing.Any]] = {
26
26
  @typing.overload
27
27
  def full_result(
28
28
  result: Result[msgspec.Raw, "APIError"], full_t: type[T]
29
- ) -> Result[T, "APIError"]:
30
- ...
29
+ ) -> Result[T, "APIError"]: ...
31
30
 
32
31
 
33
32
  @typing.overload
34
33
  def full_result(
35
34
  result: Result[msgspec.Raw, "APIError"],
36
35
  full_t: tuple[type[T], ...],
37
- ) -> Result[T, "APIError"]:
38
- ...
36
+ ) -> Result[T, "APIError"]: ...
39
37
 
40
38
 
41
39
  def full_result(
@@ -65,7 +63,7 @@ class Model(msgspec.Struct, **MODEL_CONFIG):
65
63
  self,
66
64
  *,
67
65
  exclude_fields: set[str] | None = None,
68
- ) -> dict[str, typing.Any]:
66
+ ) -> dict[str, typing.Any]:
69
67
  exclude_fields = exclude_fields or set()
70
68
  if "model_as_dict" not in self.__dict__:
71
69
  self.__dict__["model_as_dict"] = msgspec.structs.asdict(self)
@@ -91,13 +89,13 @@ class DataConverter:
91
89
  return {
92
90
  get_origin(value.__annotations__["data"]): value
93
91
  for key, value in vars(self.__class__).items()
94
- if key.startswith("convert_") and callable(value)
92
+ if key.startswith("convert_") and callable(value)
95
93
  }
96
94
 
97
95
  @staticmethod
98
96
  def convert_enum(data: enum.Enum, _: bool = True) -> typing.Any:
99
97
  return data.value
100
-
98
+
101
99
  @staticmethod
102
100
  def convert_datetime(data: datetime, _: bool = True) -> int:
103
101
  return int(data.timestamp())
@@ -109,29 +107,45 @@ class DataConverter:
109
107
  return converter(data, serialize)
110
108
  return converter(self, data, serialize)
111
109
  return data
112
-
110
+
113
111
  def get_converter(self, t: type[typing.Any]):
114
112
  for type, converter in self.converters.items():
115
113
  if issubclass(t, type):
116
114
  return converter
117
115
  return None
118
-
119
- def convert_model(self, data: Model, serialize: bool = True) -> str | dict[str, typing.Any]:
116
+
117
+ def convert_model(
118
+ self,
119
+ data: Model,
120
+ serialize: bool = True,
121
+ ) -> str | dict[str, typing.Any]:
120
122
  converted_dct = self(data.to_dict(), serialize=False)
121
123
  return encoder.encode(converted_dct) if serialize is True else converted_dct
122
-
123
- def convert_dct(self, data: dict[str, typing.Any], serialize: bool = True) -> dict[str, typing.Any]:
124
+
125
+ def convert_dct(
126
+ self,
127
+ data: dict[str, typing.Any],
128
+ serialize: bool = True,
129
+ ) -> dict[str, typing.Any]:
124
130
  return {
125
131
  k: self(v, serialize=serialize)
126
132
  for k, v in data.items()
127
133
  if type(v) not in (NoneType, Nothing)
128
134
  }
129
-
130
- def convert_lst(self, data: list[typing.Any], serialize: bool = True) -> str | list[typing.Any]:
135
+
136
+ def convert_lst(
137
+ self,
138
+ data: list[typing.Any],
139
+ serialize: bool = True,
140
+ ) -> str | list[typing.Any]:
131
141
  converted_lst = [self(x, serialize=False) for x in data]
132
142
  return encoder.encode(converted_lst) if serialize is True else converted_lst
133
-
134
- def convert_tpl(self, data: tuple[typing.Any, ...], _: bool = True) -> str | tuple[typing.Any, ...]:
143
+
144
+ def convert_tpl(
145
+ self,
146
+ data: tuple[typing.Any, ...],
147
+ _: bool = True,
148
+ ) -> str | tuple[typing.Any, ...]:
135
149
  if (
136
150
  isinstance(data, tuple)
137
151
  and len(data) == 2
@@ -142,12 +156,12 @@ class DataConverter:
142
156
  self.files[attach_name] = data
143
157
  return "attach://{}".format(attach_name)
144
158
  return data
145
-
159
+
146
160
 
147
161
  __all__ = (
148
162
  "DataConverter",
163
+ "MODEL_CONFIG",
149
164
  "Model",
150
165
  "full_result",
151
166
  "get_params",
152
- "MODEL_CONFIG",
153
167
  )
telegrinder/modules.py CHANGED
@@ -6,32 +6,24 @@ from choicelib import choice_in_order
6
6
 
7
7
  @typing.runtime_checkable
8
8
  class JSONModule(typing.Protocol):
9
- def loads(self, s: str | bytes) -> typing.Any:
10
- ...
9
+ def loads(self, s: str | bytes) -> typing.Any: ...
11
10
 
12
- def dumps(self, o: typing.Any) -> str:
13
- ...
11
+ def dumps(self, o: typing.Any) -> str: ...
14
12
 
15
13
 
16
14
  @typing.runtime_checkable
17
15
  class LoggerModule(typing.Protocol):
18
- def debug(self, __msg: object, *args: object, **kwargs: object) -> None:
19
- ...
16
+ def debug(self, __msg: object, *args: object, **kwargs: object) -> None: ...
20
17
 
21
- def info(self, __msg: object, *args: object, **kwargs: object) -> None:
22
- ...
18
+ def info(self, __msg: object, *args: object, **kwargs: object) -> None: ...
23
19
 
24
- def warning(self, __msg: object, *args: object, **kwargs: object) -> None:
25
- ...
20
+ def warning(self, __msg: object, *args: object, **kwargs: object) -> None: ...
26
21
 
27
- def error(self, __msg: object, *args: object, **kwargs: object) -> None:
28
- ...
22
+ def error(self, __msg: object, *args: object, **kwargs: object) -> None: ...
29
23
 
30
- def critical(self, __msg: object, *args: object, **kwargs: object) -> None:
31
- ...
24
+ def critical(self, __msg: object, *args: object, **kwargs: object) -> None: ...
32
25
 
33
- def exception(self, __msg: object, *args: object, **kwargs: object) -> None:
34
- ...
26
+ def exception(self, __msg: object, *args: object, **kwargs: object) -> None: ...
35
27
 
36
28
  def set_level(
37
29
  self,
@@ -43,8 +35,7 @@ class LoggerModule(typing.Protocol):
43
35
  "CRITICAL",
44
36
  "EXCEPTION",
45
37
  ],
46
- ) -> None:
47
- ...
38
+ ) -> None: ...
48
39
 
49
40
 
50
41
  logger: LoggerModule
@@ -147,8 +138,7 @@ elif logging_module == "logging":
147
138
  },
148
139
  }
149
140
  FORMAT = (
150
- FORMAT
151
- .replace("<white>", COLORS["white"])
141
+ FORMAT.replace("<white>", COLORS["white"])
152
142
  .replace("</white>", COLORS["reset"])
153
143
  .replace("<green>", COLORS["green"])
154
144
  .replace("</green>", COLORS["reset"])
@@ -157,24 +147,20 @@ elif logging_module == "logging":
157
147
  for level, settings in LEVEL_SETTINGS.items():
158
148
  fmt = FORMAT
159
149
  for name, color in settings.items():
160
- fmt = (
161
- fmt
162
- .replace(f"<{name}>", COLORS[color])
163
- .replace(f"</{name}>", COLORS["reset"])
150
+ fmt = fmt.replace(f"<{name}>", COLORS[color]).replace(
151
+ f"</{name}>", COLORS["reset"]
164
152
  )
165
153
  LEVEL_FORMATS[level] = fmt
166
154
 
167
-
168
155
  class TelegrinderLoggingFormatter(logging.Formatter):
169
- def format(self, record: logging.LogRecord) -> str:
156
+ def format(self, record: logging.LogRecord) -> str:
170
157
  if not record.funcName or record.funcName == "<module>":
171
158
  record.funcName = "\b"
172
159
  frame = next(
173
160
  (
174
161
  frame
175
162
  for frame in inspect.stack()
176
- if frame.filename == record.pathname
177
- and frame.lineno == record.lineno
163
+ if frame.filename == record.pathname and frame.lineno == record.lineno
178
164
  ),
179
165
  None,
180
166
  )
@@ -187,7 +173,6 @@ elif logging_module == "logging":
187
173
  style="{",
188
174
  ).format(record)
189
175
 
190
-
191
176
  class LogMessage:
192
177
  def __init__(self, fmt: typing.Any, args: typing.Any, kwargs: typing.Any) -> None:
193
178
  self.fmt = fmt
@@ -197,7 +182,6 @@ elif logging_module == "logging":
197
182
  def __str__(self) -> str:
198
183
  return self.fmt.format(*self.args, **self.kwargs)
199
184
 
200
-
201
185
  class TelegrinderLoggingStyleAdapter(logging.LoggerAdapter):
202
186
  def __init__(
203
187
  self,
@@ -223,7 +207,7 @@ elif logging_module == "logging":
223
207
  for key in inspect.getfullargspec(self.logger._log).args[1:]
224
208
  if key in kwargs
225
209
  }
226
-
210
+
227
211
  if isinstance(msg, str):
228
212
  msg = LogMessage(msg, args, kwargs)
229
213
  args = tuple()
@@ -245,7 +229,7 @@ def _set_logger_level(level):
245
229
  logging.getLogger("telegrinder").setLevel(logging.getLevelName(level))
246
230
  elif logging_module == "loguru":
247
231
  import loguru # type: ignore
248
-
232
+
249
233
  if handler_id in loguru.logger._core.handlers: # type: ignore
250
234
  loguru.logger._core.handlers[handler_id]._levelno = loguru.logger.level(level).no # type: ignore
251
235