dublib 0.30.2__tar.gz → 0.30.4__tar.gz

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.
Files changed (73) hide show
  1. {dublib-0.30.2 → dublib-0.30.4}/PKG-INFO +1 -1
  2. {dublib-0.30.2 → dublib-0.30.4}/pyproject.toml +2 -2
  3. {dublib-0.30.2 → dublib-0.30.4}/pyproject.toml.orig +2 -2
  4. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/functions/data/__init__.py +10 -25
  5. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/functions/data/dictionary.py +65 -0
  6. dublib-0.30.4/src/dublib/functions/data/sequences.py +28 -0
  7. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/web_requestor/config/authorization.py +45 -26
  8. {dublib-0.30.2 → dublib-0.30.4}/LICENSE +0 -0
  9. {dublib-0.30.2 → dublib-0.30.4}/README.md +0 -0
  10. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/__init__.py +0 -0
  11. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/progress_indicator.py +0 -0
  12. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/readline.py +0 -0
  13. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/templates/__init__.py +0 -0
  14. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/templates/bus.py +0 -0
  15. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/terminalyzer/__init__.py +0 -0
  16. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/terminalyzer/commands/__init__.py +0 -0
  17. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/terminalyzer/commands/group.py +0 -0
  18. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/terminalyzer/commands/identificator.py +0 -0
  19. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/terminalyzer/commands/model.py +0 -0
  20. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/terminalyzer/commands/parameters.py +0 -0
  21. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/terminalyzer/commands/positions.py +0 -0
  22. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/terminalyzer/helper/__init__.py +0 -0
  23. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/terminalyzer/helper/options.py +0 -0
  24. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/terminalyzer/parser/__init__.py +0 -0
  25. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/terminalyzer/parser/entitites.py +0 -0
  26. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/terminalyzer/parser/typing.py +0 -0
  27. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/text_styler/__init__.py +0 -0
  28. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/text_styler/codes.py +0 -0
  29. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/text_styler/escapes.py +0 -0
  30. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/cli/text_styler/fast_styler.py +0 -0
  31. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/core.py +0 -0
  32. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/engine/bus/__init__.py +0 -0
  33. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/engine/bus/enums.py +0 -0
  34. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/engine/bus/messages.py +0 -0
  35. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/engine/configurator.py +0 -0
  36. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/engine/get_text.py +0 -0
  37. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/engine/patcher.py +0 -0
  38. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/exceptions/__init__.py +0 -0
  39. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/exceptions/cli/__init__.py +0 -0
  40. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/exceptions/cli/terminalyzer/__init__.py +0 -0
  41. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/exceptions/cli/terminalyzer/groups.py +0 -0
  42. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/exceptions/cli/terminalyzer/parameters.py +0 -0
  43. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/exceptions/cli/terminalyzer/positions.py +0 -0
  44. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/exceptions/engine/__init__.py +0 -0
  45. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/exceptions/engine/bus.py +0 -0
  46. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/exceptions/telebot_utils.py +0 -0
  47. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/exceptions/validators.py +0 -0
  48. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/exceptions/web_requestor.py +0 -0
  49. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/functions/data/string.py +0 -0
  50. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/functions/decorators.py +0 -0
  51. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/functions/filesystem/__init__.py +0 -0
  52. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/functions/filesystem/json.py +0 -0
  53. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/functions/filesystem/text.py +0 -0
  54. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/functions/filesystem/yaml.py +0 -0
  55. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/functions/system.py +0 -0
  56. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/polyglot/__init__.py +0 -0
  57. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/polyglot/html.py +0 -0
  58. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/polyglot/markdown.py +0 -0
  59. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/py.typed +0 -0
  60. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/telebot_utils/cache.py +0 -0
  61. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/telebot_utils/master/__init__.py +0 -0
  62. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/telebot_utils/master/decorators.py +0 -0
  63. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/telebot_utils/users.py +0 -0
  64. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/validators/__init__.py +0 -0
  65. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/validators/base.py +0 -0
  66. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/validators/types.py +0 -0
  67. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/web_requestor/__init__.py +0 -0
  68. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/web_requestor/config/__init__.py +0 -0
  69. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/web_requestor/config/constants.py +0 -0
  70. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/web_requestor/config/headers.py +0 -0
  71. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/web_requestor/enums.py +0 -0
  72. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/web_requestor/proxy.py +0 -0
  73. {dublib-0.30.2 → dublib-0.30.4}/src/dublib/web_requestor/response.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dublib
3
- Version: 0.30.2
3
+ Version: 0.30.4
4
4
  Summary: Коллекция полезных модулей от DUB1401.
5
5
  Author: DUB1401
6
6
  Author-email: DUB1401 <vlad.milosta@outlook.com>
@@ -1,10 +1,10 @@
1
1
  [build-system]
2
- requires = ["uv-build>=0.12.10,<0.13.0"]
2
+ requires = ["uv-build>=0.12.14,<0.13.0"]
3
3
  build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "dublib"
7
- version = "0.30.2"
7
+ version = "0.30.4"
8
8
  description = "Коллекция полезных модулей от DUB1401."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -1,10 +1,10 @@
1
1
  [build-system]
2
- requires = ["uv-build>=0.12.10,<0.13.0"]
2
+ requires = ["uv-build>=0.12.14,<0.13.0"]
3
3
  build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "dublib"
7
- version = "0.30.2"
7
+ version = "0.30.4"
8
8
  description = "Коллекция полезных модулей от DUB1401."
9
9
  authors = [
10
10
  {name = "DUB1401", email = "vlad.milosta@outlook.com"}
@@ -1,10 +1,19 @@
1
1
  import copy
2
- from typing import Any, Sequence, overload
2
+ from typing import Any, Sequence
3
3
 
4
4
  import orjson
5
5
 
6
6
  from . import dictionary as dictionary
7
7
  from . import string as string
8
+ from .sequences import to_sequence
9
+
10
+ __all__ = [
11
+ "deep_copy",
12
+ "stringify_float",
13
+ "string_to_bool",
14
+ "to_sequence",
15
+ "zerotify"
16
+ ]
8
17
 
9
18
  def deep_copy(data: Any) -> Any:
10
19
  """
@@ -56,30 +65,6 @@ def string_to_bool(value: str, literals: Sequence[str] = ("false", "0")) -> bool
56
65
 
57
66
  return bool(value)
58
67
 
59
- @overload
60
- def to_sequence(value: Any, target_type: type[list]) -> list: ...
61
- @overload
62
- def to_sequence(value: Any, target_type: type[set]) -> set: ...
63
- @overload
64
- def to_sequence(value: Any, target_type: type[tuple] = ...) -> tuple: ...
65
-
66
- def to_sequence(value: Any, target_type: type[list | set | tuple] = tuple) -> list | set | tuple:
67
- """
68
- Преобразует значение в итерируемый контейнерн целевого типа.
69
-
70
- :param value: Обрабатываемое значение или итерируемый контейнер значений.
71
- :type value: Any
72
- :param target_type: Целевой тип итерируемого контейнера.
73
- :type target_type: type[list | set | tuple]
74
- :return: Приведённое к итерируемому контейнеру значение (единичные элементы упаковываются в контейнер, контейнеры преобразуются в целевой тип).
75
- :rtype: list | set | tuple
76
- """
77
-
78
- if type(value) is target_type: return value
79
- if type(value) in (list, set, tuple): return target_type(value)
80
-
81
- return target_type((value,))
82
-
83
68
  def zerotify(value: Any) -> Any:
84
69
  """
85
70
  Преобразует значения, логически интерпретируемые в `False`, в тип `None`.
@@ -1,7 +1,72 @@
1
+ from collections.abc import Sequence
1
2
  from typing import Any
2
3
 
3
4
  import more_itertools
4
5
 
6
+ from .sequences import to_sequence
7
+
8
+ def deep_merge(
9
+ base: dict,
10
+ content: dict,
11
+ sequences_type: type[list | tuple | set] = list,
12
+ uniqueness: bool = False
13
+ ) -> dict:
14
+ """
15
+ Выполняет глубокое слияние двух словарей и вложенных последовательностей `list`, `tuple` и `set`.
16
+
17
+ :param base: Базовый словарь. Изменяется во время выполнения функции.
18
+ :type base: dict
19
+ :param content: Словарь, содержимое которого вливается в базовый.
20
+ :type content: dict
21
+ :param sequences_type: Тип, к которому будут приводиться последовательности при их слиянии.
22
+ :type sequences_type: type[list | tuple | set]
23
+ :param uniqueness: Указывает, нужно ли исключать в последовательностях повторяемые элементы.
24
+ :type uniqueness: bool
25
+ :return: Базовый словарь.
26
+ :rtype: dict
27
+ """
28
+
29
+ for key, content_value in content.items():
30
+
31
+ #---> Простое добавление.
32
+ #==========================================================================================#
33
+ if key not in base:
34
+ base[key] = content_value
35
+ continue
36
+
37
+ base_value = base[key]
38
+
39
+ #---> Слияние словарей.
40
+ #==========================================================================================#
41
+ if isinstance(base_value, dict) and isinstance(content_value, dict):
42
+ base_value = deep_merge(base_value, content_value, sequences_type, uniqueness)
43
+ continue
44
+
45
+ #---> Слияние последовательностей.
46
+ #==========================================================================================#
47
+ if all(isinstance(value, Sequence) and not isinstance(value, (str, bytes)) for value in (base_value, content_value)):
48
+ base_list: list = to_sequence(base_value, target_type = list)
49
+ content_list: list = to_sequence(content_value, target_type = list)
50
+ result_list: list = []
51
+
52
+ if uniqueness:
53
+ for item in content_list:
54
+ if item not in base_list:
55
+ base_list.append(item)
56
+ result_list = base_list
57
+
58
+ else:
59
+ result_list = base_list + content_list
60
+
61
+ base[key] = to_sequence(result_list, target_type = sequences_type)
62
+ continue
63
+
64
+ #---> Перезапись.
65
+ #==========================================================================================#
66
+ base[key] = content_value
67
+
68
+ return base
69
+
5
70
  def insert_item(base_dictionary: dict, target_key: Any, item: tuple[Any, Any]) -> dict:
6
71
  """
7
72
  Вставляет пару ключ-значение после определённого ключа.
@@ -0,0 +1,28 @@
1
+ from typing import Any, overload
2
+
3
+ from . import dictionary as dictionary
4
+ from . import string as string
5
+
6
+ @overload
7
+ def to_sequence(value: Any, target_type: type[list]) -> list: ...
8
+ @overload
9
+ def to_sequence(value: Any, target_type: type[set]) -> set: ...
10
+ @overload
11
+ def to_sequence(value: Any, target_type: type[tuple] = ...) -> tuple: ...
12
+
13
+ def to_sequence(value: Any, target_type: type[list | set | tuple] = tuple) -> list | set | tuple:
14
+ """
15
+ Преобразует значение в итерируемый контейнерн целевого типа.
16
+
17
+ :param value: Обрабатываемое значение или итерируемый контейнер значений.
18
+ :type value: Any
19
+ :param target_type: Целевой тип итерируемого контейнера.
20
+ :type target_type: type[list | set | tuple]
21
+ :return: Приведённое к итерируемому контейнеру значение (единичные элементы упаковываются в контейнер, контейнеры преобразуются в целевой тип).
22
+ :rtype: list | set | tuple
23
+ """
24
+
25
+ if type(value) is target_type: return value
26
+ if type(value) in (list, set, tuple): return target_type(value)
27
+
28
+ return target_type((value,))
@@ -37,39 +37,38 @@ class _BaseAuthorizationMethod(ABC):
37
37
  return self._Value
38
38
 
39
39
  @property
40
- def scheme(self) -> str:
40
+ def scheme(self) -> AuthorizationSchemes:
41
41
  """Схема авторизации."""
42
42
 
43
- return self._Scheme.value
43
+ return self._Scheme
44
44
 
45
45
  #==========================================================================================#
46
46
  # >>>>> НАСЛЕДУЕМЫЕ МЕТОДЫ <<<<< #
47
47
  #==========================================================================================#
48
48
 
49
- def _ClearScheme(self, token: str) -> str:
49
+ def _remove_scheme(self, data: str) -> str:
50
50
  """
51
- Удаляет из токена схему.
51
+ Удаляет из данных авторизации схему.
52
52
 
53
- :param token: Токен.
54
- :type token: str
55
- :return: Обработанный токен.
53
+ :param data: Данные авторизации.
54
+ :type data: str
55
+ :return: Очищенные данные.
56
56
  :rtype: str
57
57
  """
58
58
 
59
- for Schema in AuthorizationSchemes:
60
- SchemaLength: int = len(Schema.value)
59
+ scheme_length: int = len(self._Scheme.value)
61
60
 
62
- if token.lower().startswith(Schema.value.lower()):
63
- return token[:SchemaLength * -1].strip()
61
+ if data.lower().startswith(self._Scheme.value.lower()):
62
+ return data[:scheme_length * -1].strip()
64
63
 
65
- return token
64
+ return data
66
65
 
67
66
  #==========================================================================================#
68
67
  # >>>>> ПЕРЕОПРЕДЕЛЯЕМЫЕ МЕТОДЫ <<<<< #
69
68
  #==========================================================================================#
70
69
 
71
70
  @abstractmethod
72
- def _ReturnScheme(self) -> AuthorizationSchemes:
71
+ def _export_scheme(self) -> AuthorizationSchemes:
73
72
  """
74
73
  Возвращает тип схемы авторизации.
75
74
 
@@ -86,7 +85,7 @@ class _BaseAuthorizationMethod(ABC):
86
85
  def __init__(self):
87
86
  """Базовый метод авторизации."""
88
87
 
89
- self._Scheme: AuthorizationSchemes = self._ReturnScheme()
88
+ self._Scheme: AuthorizationSchemes = self._export_scheme()
90
89
  self._Value: str | None = None
91
90
 
92
91
  def clear(self):
@@ -101,7 +100,7 @@ class Basic(_BaseAuthorizationMethod):
101
100
  # >>>>> ПЕРЕОПРЕДЕЛЯЕМЫЕ МЕТОДЫ <<<<< #
102
101
  #==========================================================================================#
103
102
 
104
- def _ReturnScheme(self) -> AuthorizationSchemes:
103
+ def _export_scheme(self) -> AuthorizationSchemes:
105
104
  """
106
105
  Возвращает тип схемы авторизации.
107
106
 
@@ -138,7 +137,7 @@ class Bearer(_BaseAuthorizationMethod):
138
137
  # >>>>> ПЕРЕОПРЕДЕЛЯЕМЫЕ МЕТОДЫ <<<<< #
139
138
  #==========================================================================================#
140
139
 
141
- def _ReturnScheme(self) -> AuthorizationSchemes:
140
+ def _export_scheme(self) -> AuthorizationSchemes:
142
141
  """
143
142
  Возвращает тип схемы авторизации.
144
143
 
@@ -152,6 +151,22 @@ class Bearer(_BaseAuthorizationMethod):
152
151
  # >>>>> ПУБЛИЧНЫЕ МЕТОДЫ <<<<< #
153
152
  #==========================================================================================#
154
153
 
154
+ def get_jwt_expiration_date(self, token: str) -> datetime:
155
+ """
156
+ Определяет дату и время истечения токена.
157
+
158
+ :param token: **JSON Web Token** со схемой или без.
159
+ :type token: str
160
+ :return: Дата и время истечения токена.
161
+ :rtype: datetime
162
+ """
163
+
164
+ token = self._remove_scheme(token)
165
+ token_data: dict = jwt.decode(token, options = {"verify_signature": False})
166
+ expiration_timestamp: int = token_data["exp"]
167
+
168
+ return datetime.fromtimestamp(expiration_timestamp)
169
+
155
170
  def is_jwt_expired(self, token: str, exception: bool = False) -> bool:
156
171
  """
157
172
  Проверяет, устарел ли **JSON Web Token**.
@@ -166,15 +181,13 @@ class Bearer(_BaseAuthorizationMethod):
166
181
  :raises TokenExpiredError: Токен устарел.
167
182
  """
168
183
 
169
- token = self._ClearScheme(token)
170
- TokenData = jwt.decode(token, options = {"verify_signature": False})
171
- ExpiratonTimestamp: int = TokenData["exp"]
172
- IsExpired: bool = ExpiratonTimestamp < time()
184
+ expiration_date = self.get_jwt_expiration_date(token)
185
+ is_expired: bool = expiration_date.timestamp() < time()
173
186
 
174
- if exception and IsExpired:
175
- raise Exceptions.TokenExpiredError(datetime.fromtimestamp(ExpiratonTimestamp))
187
+ if exception and is_expired:
188
+ raise Exceptions.TokenExpiredError(expiration_date)
176
189
 
177
- return IsExpired
190
+ return is_expired
178
191
 
179
192
  def set_jwt(self, token: str, validate: bool = True):
180
193
  """
@@ -188,7 +201,7 @@ class Bearer(_BaseAuthorizationMethod):
188
201
  """
189
202
 
190
203
  if validate: self.is_jwt_expired(token, exception = True)
191
- self._Value = self._ClearScheme(token)
204
+ self._Value = self._remove_scheme(token)
192
205
 
193
206
  def set_token(self, token: str):
194
207
  """
@@ -198,7 +211,7 @@ class Bearer(_BaseAuthorizationMethod):
198
211
  :type token: str
199
212
  """
200
213
 
201
- self._Value = self._ClearScheme(token)
214
+ self._Value = self._remove_scheme(token)
202
215
 
203
216
  #==========================================================================================#
204
217
  # >>>>> ОСНОВНОЙ КЛАСС <<<<< #
@@ -218,7 +231,13 @@ class Authorizator:
218
231
  if not self.__IsEnabled or not self.__AuthorizationMethod:
219
232
  return {}
220
233
 
221
- return {constants.AUTHORIZATION_HEADER: f"{self.__AuthorizationMethod.scheme} {self.__AuthorizationMethod.value}"}
234
+ return {constants.AUTHORIZATION_HEADER: f"{self.__AuthorizationMethod.scheme.value} {self.__AuthorizationMethod.value}"}
235
+
236
+ @property
237
+ def method(self) -> _BaseAuthorizationMethod | None:
238
+ """Используемый метод авторизации."""
239
+
240
+ return self.__AuthorizationMethod
222
241
 
223
242
  #==========================================================================================#
224
243
  # >>>>> ПУБЛИЧНЫЕ МЕТОДЫ <<<<< #
File without changes
File without changes
File without changes
File without changes
File without changes