telegrinder 0.1.dev169__tar.gz → 0.1.dev170__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.

Potentially problematic release.


This version of telegrinder might be problematic. Click here for more details.

Files changed (143) hide show
  1. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/PKG-INFO +2 -2
  2. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/pyproject.toml +13 -2
  3. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/model.py +2 -1
  4. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/msgspec_utils.py +61 -8
  5. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/LICENSE +0 -0
  6. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/readme.md +0 -0
  7. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/__init__.py +0 -0
  8. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/api/__init__.py +0 -0
  9. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/api/abc.py +0 -0
  10. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/api/api.py +0 -0
  11. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/api/error.py +0 -0
  12. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/api/response.py +0 -0
  13. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/__init__.py +0 -0
  14. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/bot.py +0 -0
  15. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/cute_types/__init__.py +0 -0
  16. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/cute_types/base.py +0 -0
  17. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/cute_types/callback_query.py +0 -0
  18. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/cute_types/chat_join_request.py +0 -0
  19. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/cute_types/chat_member_updated.py +0 -0
  20. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/cute_types/inline_query.py +0 -0
  21. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/cute_types/message.py +0 -0
  22. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/cute_types/update.py +0 -0
  23. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/cute_types/utils.py +0 -0
  24. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/__init__.py +0 -0
  25. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/abc.py +0 -0
  26. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/context.py +0 -0
  27. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/dispatch.py +0 -0
  28. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/handler/__init__.py +0 -0
  29. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/handler/abc.py +0 -0
  30. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/handler/func.py +0 -0
  31. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/handler/message_reply.py +0 -0
  32. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/middleware/__init__.py +0 -0
  33. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/middleware/abc.py +0 -0
  34. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/process.py +0 -0
  35. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/return_manager/__init__.py +0 -0
  36. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/return_manager/abc.py +0 -0
  37. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/return_manager/callback_query.py +0 -0
  38. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/return_manager/inline_query.py +0 -0
  39. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/return_manager/message.py +0 -0
  40. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/view/__init__.py +0 -0
  41. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/view/abc.py +0 -0
  42. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/view/box.py +0 -0
  43. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/view/callback_query.py +0 -0
  44. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/view/chat_join_request.py +0 -0
  45. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/view/chat_member.py +0 -0
  46. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/view/inline_query.py +0 -0
  47. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/view/message.py +0 -0
  48. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/view/raw.py +0 -0
  49. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/waiter_machine/__init__.py +0 -0
  50. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/waiter_machine/machine.py +0 -0
  51. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/waiter_machine/middleware.py +0 -0
  52. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/dispatch/waiter_machine/short_state.py +0 -0
  53. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/polling/__init__.py +0 -0
  54. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/polling/abc.py +0 -0
  55. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/polling/polling.py +0 -0
  56. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/__init__.py +0 -0
  57. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/abc.py +0 -0
  58. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/adapter/__init__.py +0 -0
  59. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/adapter/abc.py +0 -0
  60. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/adapter/errors.py +0 -0
  61. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/adapter/event.py +0 -0
  62. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/adapter/node.py +0 -0
  63. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/adapter/raw_update.py +0 -0
  64. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/callback_data.py +0 -0
  65. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/chat_join.py +0 -0
  66. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/command.py +0 -0
  67. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/enum_text.py +0 -0
  68. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/func.py +0 -0
  69. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/fuzzy.py +0 -0
  70. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/inline.py +0 -0
  71. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/integer.py +0 -0
  72. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/is_from.py +0 -0
  73. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/markup.py +0 -0
  74. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/mention.py +0 -0
  75. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/message.py +0 -0
  76. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/message_entities.py +0 -0
  77. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/node.py +0 -0
  78. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/regex.py +0 -0
  79. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/rule_enum.py +0 -0
  80. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/start.py +0 -0
  81. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/text.py +0 -0
  82. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/rules/update.py +0 -0
  83. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/scenario/__init__.py +0 -0
  84. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/scenario/abc.py +0 -0
  85. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/scenario/checkbox.py +0 -0
  86. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/bot/scenario/choice.py +0 -0
  87. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/client/__init__.py +0 -0
  88. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/client/abc.py +0 -0
  89. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/client/aiohttp.py +0 -0
  90. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/modules.py +0 -0
  91. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/msgspec_json.py +0 -0
  92. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/__init__.py +0 -0
  93. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/attachment.py +0 -0
  94. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/base.py +0 -0
  95. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/callback_query.py +0 -0
  96. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/command.py +0 -0
  97. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/composer.py +0 -0
  98. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/container.py +0 -0
  99. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/me.py +0 -0
  100. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/message.py +0 -0
  101. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/polymorphic.py +0 -0
  102. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/rule.py +0 -0
  103. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/scope.py +0 -0
  104. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/source.py +0 -0
  105. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/text.py +0 -0
  106. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/tools/__init__.py +0 -0
  107. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/tools/generator.py +0 -0
  108. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/node/update.py +0 -0
  109. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/rules.py +0 -0
  110. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/__init__.py +0 -0
  111. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/buttons.py +0 -0
  112. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/error_handler/__init__.py +0 -0
  113. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/error_handler/abc.py +0 -0
  114. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/error_handler/error.py +0 -0
  115. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/error_handler/error_handler.py +0 -0
  116. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/formatting/__init__.py +0 -0
  117. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/formatting/html.py +0 -0
  118. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/formatting/links.py +0 -0
  119. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/formatting/spec_html_formats.py +0 -0
  120. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/global_context/__init__.py +0 -0
  121. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/global_context/abc.py +0 -0
  122. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/global_context/global_context.py +0 -0
  123. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/global_context/telegrinder_ctx.py +0 -0
  124. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/i18n/__init__.py +0 -0
  125. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/i18n/base.py +0 -0
  126. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/i18n/middleware/__init__.py +0 -0
  127. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/i18n/middleware/base.py +0 -0
  128. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/i18n/simple.py +0 -0
  129. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/kb_set/__init__.py +0 -0
  130. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/kb_set/base.py +0 -0
  131. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/kb_set/yaml.py +0 -0
  132. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/keyboard.py +0 -0
  133. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/limited_dict.py +0 -0
  134. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/loop_wrapper/__init__.py +0 -0
  135. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/loop_wrapper/abc.py +0 -0
  136. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/loop_wrapper/loop_wrapper.py +0 -0
  137. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/magic.py +0 -0
  138. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/tools/parse_mode.py +0 -0
  139. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/types/__init__.py +0 -0
  140. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/types/enums.py +0 -0
  141. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/types/methods.py +0 -0
  142. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/types/objects.py +0 -0
  143. {telegrinder-0.1.dev169 → telegrinder-0.1.dev170}/telegrinder/verification_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: telegrinder
3
- Version: 0.1.dev169
3
+ Version: 0.1.dev170
4
4
  Summary: Modern visionary telegram bot framework.
5
5
  Home-page: https://github.com/timoniq/telegrinder
6
6
  License: MIT
@@ -25,7 +25,7 @@ Requires-Dist: certifi (>=2024.2.2,<2025.0.0)
25
25
  Requires-Dist: choicelib (>=0.1.5,<0.2.0)
26
26
  Requires-Dist: colorama (>=0.4.0,<0.5.0)
27
27
  Requires-Dist: envparse (>=0.2.0,<0.3.0)
28
- Requires-Dist: fntypes (>=0.1.2.post1,<0.2.0)
28
+ Requires-Dist: fntypes (>=0.1.2.post2,<0.2.0)
29
29
  Requires-Dist: msgspec (>=0.18.6,<0.19.0)
30
30
  Requires-Dist: requests (>=2.28.1,<3.0.0)
31
31
  Requires-Dist: typing-extensions (>=4.10.0,<5.0.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "telegrinder"
3
- version = "0.1.dev169"
3
+ version = "0.1.dev170"
4
4
  description = "Modern visionary telegram bot framework."
5
5
  authors = ["timoniq <tesseradecades@mail.ru>"]
6
6
  maintainers = ["luwqz1 <howluwqz1@gmail.com>"]
@@ -49,7 +49,7 @@ certifi = "^2024.2.2"
49
49
  msgspec = "^0.18.6"
50
50
  requests = "^2.28.1"
51
51
  typing-extensions = "^4.10.0"
52
- fntypes = "^0.1.2.post1"
52
+ fntypes = "^0.1.2.post2"
53
53
 
54
54
  [tool.poetry.group.dev.dependencies]
55
55
  ruff = "^0.5.0"
@@ -84,4 +84,15 @@ asyncio_mode = "auto"
84
84
  docstring-quotes = "double"
85
85
 
86
86
  [tool.pyright]
87
+ exclude = [
88
+ "**/__pycache__",
89
+ "examples/blueprint_bot",
90
+ "examples/webhook_bot",
91
+ "docs",
92
+ "local",
93
+ ]
87
94
  typeCheckingMode = "basic"
95
+ pythonPlatform = "All"
96
+ pythonVersion = "3.11"
97
+ reportMissingImports = true
98
+ reportMissingTypeStubs = false
@@ -1,5 +1,6 @@
1
1
  import dataclasses
2
2
  import enum
3
+ import keyword
3
4
  import secrets
4
5
  import typing
5
6
  from datetime import datetime
@@ -19,7 +20,7 @@ T = typing.TypeVar("T")
19
20
  MODEL_CONFIG: typing.Final[dict[str, typing.Any]] = {
20
21
  "omit_defaults": True,
21
22
  "dict": True,
22
- "rename": {"from_": "from"},
23
+ "rename": {kw + "_": kw for kw in keyword.kwlist},
23
24
  }
24
25
 
25
26
 
@@ -1,6 +1,7 @@
1
1
  import typing
2
2
 
3
3
  import fntypes.option
4
+ import fntypes.result
4
5
  import msgspec
5
6
  from fntypes.co import Error, Ok, Result, Variative
6
7
 
@@ -8,10 +9,12 @@ if typing.TYPE_CHECKING:
8
9
  from datetime import datetime
9
10
 
10
11
  from fntypes.option import Option
12
+ from fntypes.result import Result
11
13
  else:
12
14
  from datetime import datetime as dt
13
15
 
14
16
  Value = typing.TypeVar("Value")
17
+ Err = typing.TypeVar("Err")
15
18
 
16
19
  datetime = type("datetime", (dt,), {})
17
20
 
@@ -19,9 +22,16 @@ else:
19
22
  def __instancecheck__(cls, __instance: typing.Any) -> bool:
20
23
  return isinstance(__instance, fntypes.option.Some | fntypes.option.Nothing)
21
24
 
25
+ class ResultMeta(type):
26
+ def __instancecheck__(cls, __instance: typing.Any) -> bool:
27
+ return isinstance(__instance, fntypes.result.Ok | fntypes.result.Error)
28
+
22
29
  class Option(typing.Generic[Value], metaclass=OptionMeta):
23
30
  pass
24
31
 
32
+ class Result(typing.Generic[Value, Err], metaclass=ResultMeta):
33
+ pass
34
+
25
35
 
26
36
  T = typing.TypeVar("T")
27
37
  Type = typing.TypeVar("Type", bound=type | typing.Any)
@@ -41,18 +51,52 @@ def repr_type(t: type) -> str:
41
51
  return getattr(t, "__name__", repr(get_origin(t)))
42
52
 
43
53
 
44
- def msgspec_convert(obj: typing.Any, t: type[T]) -> Result[T, msgspec.ValidationError]:
54
+ def msgspec_convert(obj: typing.Any, t: type[T]) -> Result[T, str]:
45
55
  try:
46
56
  return Ok(decoder.convert(obj, type=t, strict=True))
47
- except msgspec.ValidationError as exc:
48
- return Error(exc)
57
+ except msgspec.ValidationError:
58
+ return Error(
59
+ "Expected object of type `{}`, got `{}`.".format(
60
+ repr_type(t),
61
+ repr_type(type(obj)),
62
+ )
63
+ )
49
64
 
50
65
 
51
66
  def option_dec_hook(tp: type[Option[typing.Any]], obj: typing.Any) -> Option[typing.Any]:
52
- if obj is None:
53
- return Nothing
67
+ orig_type = get_origin(tp)
54
68
  (value_type,) = typing.get_args(tp) or (typing.Any,)
55
- return msgspec_convert({"value": obj}, fntypes.option.Some[value_type]).unwrap()
69
+
70
+ if obj is None and orig_type in (fntypes.option.Nothing, Option):
71
+ return fntypes.option.Nothing()
72
+ return fntypes.option.Some(msgspec_convert(obj, value_type).unwrap())
73
+
74
+
75
+ def result_dec_hook(
76
+ tp: type[Result[typing.Any, typing.Any]], obj: typing.Any
77
+ ) -> Result[typing.Any, typing.Any]:
78
+ if not isinstance(obj, dict):
79
+ raise TypeError(f"Cannot parse to Result object of type `{repr_type(type(obj))}`.")
80
+
81
+ orig_type = get_origin(tp)
82
+ (first_type, second_type) = (
83
+ typing.get_args(tp) + (typing.Any,) if len(typing.get_args(tp)) == 1 else typing.get_args(tp)
84
+ ) or (typing.Any, typing.Any)
85
+
86
+ if orig_type is Ok and "ok" in obj:
87
+ return Ok(msgspec_convert(obj["ok"], first_type).unwrap())
88
+
89
+ if orig_type is Error and "error" in obj:
90
+ return Error(msgspec_convert(obj["error"], first_type).unwrap())
91
+
92
+ if orig_type is Result:
93
+ match obj:
94
+ case {"ok": ok}:
95
+ return Ok(msgspec_convert(ok, first_type).unwrap())
96
+ case {"error": error}:
97
+ return Error(msgspec_convert(error, second_type).unwrap())
98
+
99
+ raise msgspec.ValidationError(f"Cannot parse object `{obj!r}` to Result.")
56
100
 
57
101
 
58
102
  def variative_dec_hook(tp: type[Variative], obj: typing.Any) -> Variative:
@@ -122,9 +166,14 @@ class Decoder:
122
166
 
123
167
  def __init__(self) -> None:
124
168
  self.dec_hooks: dict[typing.Any, DecHook[typing.Any]] = {
169
+ Result: result_dec_hook,
125
170
  Option: option_dec_hook,
126
171
  Variative: variative_dec_hook,
127
172
  datetime: lambda t, obj: t.fromtimestamp(obj),
173
+ fntypes.result.Error: result_dec_hook,
174
+ fntypes.result.Ok: result_dec_hook,
175
+ fntypes.option.Some: option_dec_hook,
176
+ fntypes.option.Nothing: option_dec_hook,
128
177
  }
129
178
 
130
179
  def __repr__(self) -> str:
@@ -143,7 +192,7 @@ class Decoder:
143
192
  origin_type = t if isinstance((t := get_origin(tp)), type) else type(t)
144
193
  if origin_type not in self.dec_hooks:
145
194
  raise TypeError(
146
- f"Unknown type `{repr_type(origin_type)}`. " "You can implement decode hook for this type."
195
+ f"Unknown type `{repr_type(origin_type)}`. You can implement decode hook for this type."
147
196
  )
148
197
  return self.dec_hooks[origin_type](tp, obj)
149
198
 
@@ -211,6 +260,10 @@ class Encoder:
211
260
  self.enc_hooks: dict[typing.Any, EncHook[typing.Any]] = {
212
261
  fntypes.option.Some: lambda opt: opt.value,
213
262
  fntypes.option.Nothing: lambda _: None,
263
+ fntypes.result.Ok: lambda ok: {"ok": ok.value},
264
+ fntypes.result.Error: lambda err: {
265
+ "error": (str(err.error) if isinstance(err.error, BaseException) else err.error)
266
+ },
214
267
  Variative: lambda variative: variative.v,
215
268
  datetime: lambda date: int(date.timestamp()),
216
269
  }
@@ -232,7 +285,7 @@ class Encoder:
232
285
  origin_type = get_origin(obj.__class__)
233
286
  if origin_type not in self.enc_hooks:
234
287
  raise NotImplementedError(
235
- "Not implemented encode hook for " f"object of type `{repr_type(origin_type)}`."
288
+ f"Not implemented encode hook for object of type `{repr_type(origin_type)}`."
236
289
  )
237
290
  return self.enc_hooks[origin_type](obj)
238
291