faster-eth-utils 5.3.12__tar.gz → 5.3.16__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 faster-eth-utils might be problematic. Click here for more details.

Files changed (83) hide show
  1. {faster_eth_utils-5.3.12/faster_eth_utils.egg-info → faster_eth_utils-5.3.16}/PKG-INFO +14 -5
  2. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/applicators.py +24 -18
  3. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/curried/__init__.py +48 -47
  4. faster_eth_utils-5.3.16/faster_eth_utils/decorators.py +119 -0
  5. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/logging.py +23 -22
  6. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/types.py +2 -2
  7. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16/faster_eth_utils.egg-info}/PKG-INFO +14 -5
  8. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils.egg-info/requires.txt +4 -2
  9. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/pyproject.toml +8 -7
  10. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/setup.py +19 -6
  11. faster_eth_utils-5.3.12/faster_eth_utils/decorators.py +0 -79
  12. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/LICENSE +0 -0
  13. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/MANIFEST.in +0 -0
  14. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/README.md +0 -0
  15. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/__init__.py +0 -0
  16. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/__json/eth_networks.json +0 -0
  17. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/__main__.py +0 -0
  18. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/abi.py +0 -0
  19. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/address.py +0 -0
  20. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/conversions.py +0 -0
  21. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/crypto.py +0 -0
  22. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/currency.py +0 -0
  23. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/debug.py +0 -0
  24. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/encoding.py +0 -0
  25. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/exceptions.py +0 -0
  26. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/functional.py +0 -0
  27. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/hexadecimal.py +0 -0
  28. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/humanize.py +0 -0
  29. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/module_loading.py +0 -0
  30. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/network.py +0 -0
  31. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/numeric.py +0 -0
  32. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/py.typed +0 -0
  33. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/pydantic.py +0 -0
  34. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/toolz.py +0 -0
  35. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/typing/__init__.py +0 -0
  36. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/typing/misc.py +0 -0
  37. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils/units.py +0 -0
  38. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils.egg-info/SOURCES.txt +0 -0
  39. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils.egg-info/dependency_links.txt +0 -0
  40. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils.egg-info/not-zip-safe +0 -0
  41. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/faster_eth_utils.egg-info/top_level.txt +0 -0
  42. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/scripts/benchmark/compare_benchmark_results.py +0 -0
  43. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/scripts/benchmark/generate_benchmark_markdown.py +0 -0
  44. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/scripts/benchmark/parse_benchmark_output.py +0 -0
  45. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/scripts/release/test_package.py +0 -0
  46. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/setup.cfg +0 -0
  47. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/abi-utils/test_abi_utils.py +0 -0
  48. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/address-utils/test_address_utils.py +0 -0
  49. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/applicator-utils/test_applicators.py +0 -0
  50. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/conversion-utils/test_conversions.py +0 -0
  51. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/currency-utils/test_currency_tools.py +0 -0
  52. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/currency-utils/test_denoms_obj.py +0 -0
  53. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/curried-utils/test_curried.py +0 -0
  54. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/decorator-utils/test_combomethod.py +0 -0
  55. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/decorator-utils/test_replace_exceptions.py +0 -0
  56. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/encoding-utils/test_big_endian_integer.py +0 -0
  57. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/functional-utils/test_return_value_decorators.py +0 -0
  58. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/functional-utils/test_type_inference.py +0 -0
  59. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/hexadecimal-utils/test_0x_prefix_addition_and_removal.py +0 -0
  60. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/hexadecimal-utils/test_is_0x_prefixed.py +0 -0
  61. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/hexadecimal-utils/test_is_hex.py +0 -0
  62. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/hexadecimal-utils/test_is_hexstr.py +0 -0
  63. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/humanize-utils/test_humanize_bytes.py +0 -0
  64. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/humanize-utils/test_humanize_hash.py +0 -0
  65. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/humanize-utils/test_humanize_hexstr.py +0 -0
  66. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/humanize-utils/test_humanize_integer_sequence.py +0 -0
  67. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/humanize-utils/test_humanize_ipfs_uri.py +0 -0
  68. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/humanize-utils/test_humanize_seconds.py +0 -0
  69. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/humanize-utils/test_humanize_wei.py +0 -0
  70. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/logging-utils/test_DEBUG2_logging.py +0 -0
  71. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/logging-utils/test_compat_with_abc_ABC.py +0 -0
  72. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/logging-utils/test_get_logger.py +0 -0
  73. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/logging-utils/test_has_logger_metaclass.py +0 -0
  74. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/module-loading-utils/test_import_string.py +0 -0
  75. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/network-utils/test_network_utils.py +0 -0
  76. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/numeric-utils/test_clamp.py +0 -0
  77. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/pydantic-utils/test_camel_model.py +0 -0
  78. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/test_import_and_version.py +0 -0
  79. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/type-checks/mypy_typing_of_curried_utils.py +0 -0
  80. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/type-checks/mypy_typing_of_functional_utils.py +0 -0
  81. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/type-checks/mypy_typing_of_has_logger.py +0 -0
  82. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/core/types-utils/test_types_utils.py +0 -0
  83. {faster_eth_utils-5.3.12 → faster_eth_utils-5.3.16}/tests/mypy/abi_types.py +0 -0
@@ -1,14 +1,21 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: faster-eth-utils
3
- Version: 5.3.12
3
+ Version: 5.3.16
4
4
  Summary: A fork of eth-utils: Common utility functions for python code that interacts with Ethereum, implemented in C
5
- Home-page: https://github.com/BobTheBuidler/eth-utils
5
+ Home-page: https://github.com/BobTheBuidler/faster-eth-utils
6
6
  Author: The Ethereum Foundation
7
7
  Author-email: snakecharmers@ethereum.org
8
8
  License: MIT
9
+ Project-URL: Documentation, https://eth-utils.readthedocs.io/en/stable/
10
+ Project-URL: Release Notes, https://github.com/BobTheBuidler/faster-eth-utils/releases
11
+ Project-URL: Issues, https://github.com/BobTheBuidler/faster-eth-utils/issues
12
+ Project-URL: Source - Precompiled (.py), https://github.com/BobTheBuidler/faster-eth-utils/tree/master/faster_eth_utils
13
+ Project-URL: Source - Compiled (.c), https://github.com/BobTheBuidler/faster-eth-utils/tree/master/build
14
+ Project-URL: Benchmarks, https://github.com/BobTheBuidler/faster-eth-utils/tree/master/benchmarks
15
+ Project-URL: Benchmarks - Results, https://github.com/BobTheBuidler/faster-eth-utils/tree/master/benchmarks/results
16
+ Project-URL: Original, https://github.com/ethereum/eth-utils
9
17
  Keywords: ethereum
10
18
  Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: MIT License
12
19
  Classifier: Natural Language :: English
13
20
  Classifier: Programming Language :: Python :: 3
14
21
  Classifier: Programming Language :: Python :: 3.8
@@ -45,7 +52,6 @@ Requires-Dist: towncrier<26,>=24; extra == "dev"
45
52
  Requires-Dist: hypothesis>=4.43.0; extra == "dev"
46
53
  Requires-Dist: mypy==1.18.2; extra == "dev"
47
54
  Requires-Dist: pytest>=7.0.0; extra == "dev"
48
- Requires-Dist: pytest-codspeed>=2.0.0; extra == "dev"
49
55
  Requires-Dist: pytest-xdist>=2.4.0; extra == "dev"
50
56
  Provides-Extra: docs
51
57
  Requires-Dist: sphinx>=6.0.0; extra == "docs"
@@ -56,8 +62,10 @@ Provides-Extra: test
56
62
  Requires-Dist: hypothesis>=4.43.0; extra == "test"
57
63
  Requires-Dist: mypy==1.18.2; extra == "test"
58
64
  Requires-Dist: pytest>=7.0.0; extra == "test"
59
- Requires-Dist: pytest-codspeed>=2.0.0; extra == "test"
60
65
  Requires-Dist: pytest-xdist>=2.4.0; extra == "test"
66
+ Provides-Extra: codspeed
67
+ Requires-Dist: pytest>=7.0.0; extra == "codspeed"
68
+ Requires-Dist: pytest-codspeed<4.3,>=4.2; extra == "codspeed"
61
69
  Dynamic: author
62
70
  Dynamic: author-email
63
71
  Dynamic: classifier
@@ -67,6 +75,7 @@ Dynamic: home-page
67
75
  Dynamic: keywords
68
76
  Dynamic: license
69
77
  Dynamic: license-file
78
+ Dynamic: project-url
70
79
  Dynamic: provides-extra
71
80
  Dynamic: requires-dist
72
81
  Dynamic: requires-python
@@ -1,4 +1,5 @@
1
1
  from typing import (
2
+ TYPE_CHECKING,
2
3
  Any,
3
4
  Callable,
4
5
  Dict,
@@ -21,9 +22,6 @@ from typing_extensions import (
21
22
  from .decorators import (
22
23
  return_arg_type,
23
24
  )
24
- from .functional import (
25
- to_dict,
26
- )
27
25
  from .pydantic import (
28
26
  CamelModel,
29
27
  )
@@ -32,6 +30,9 @@ from .toolz import (
32
30
  curry,
33
31
  )
34
32
 
33
+ if TYPE_CHECKING:
34
+ from _typeshed import SupportsBool
35
+
35
36
  TArg = TypeVar("TArg")
36
37
  TReturn = TypeVar("TReturn")
37
38
  TOther = TypeVar("TOther")
@@ -41,7 +42,9 @@ Formatters = Callable[[List[Any]], List[Any]]
41
42
 
42
43
  @return_arg_type(2)
43
44
  def apply_formatter_at_index(
44
- formatter: Callable[[TArg], TReturn], at_index: int, value: Sequence[Union[TArg, TOther]]
45
+ formatter: Callable[[TArg], TReturn],
46
+ at_index: int,
47
+ value: Sequence[Union[TArg, TOther]],
45
48
  ) -> Generator[Union[TOther, TReturn], None, None]:
46
49
  try:
47
50
  item = value[at_index]
@@ -69,7 +72,7 @@ def combine_argument_formatters(*formatters: Callable[..., Any]) -> Formatters:
69
72
  )
70
73
 
71
74
  _formatter_at_index = curry(apply_formatter_at_index)
72
- return compose( # type: ignore
75
+ return compose( # type: ignore [no-any-return]
73
76
  *(
74
77
  _formatter_at_index(formatter, index)
75
78
  for index, formatter in enumerate(formatters)
@@ -100,14 +103,18 @@ def apply_formatters_to_sequence(
100
103
 
101
104
  @overload
102
105
  def apply_formatter_if(
103
- condition: Callable[[TArg], TypeGuard[TOther]], formatter: Callable[[TOther], TReturn], value: TArg
106
+ condition: Callable[[TArg], TypeGuard[TOther]],
107
+ formatter: Callable[[TOther], TReturn],
108
+ value: TArg,
104
109
  ) -> Union[TArg, TReturn]: ...
105
110
 
111
+
106
112
  @overload
107
113
  def apply_formatter_if(
108
114
  condition: Callable[[TArg], bool], formatter: Callable[[TArg], TReturn], value: TArg
109
115
  ) -> Union[TArg, TReturn]: ...
110
116
 
117
+
111
118
  def apply_formatter_if( # type: ignore [misc]
112
119
  condition: Union[Callable[[TArg], TypeGuard[TOther]], Callable[[TArg], bool]],
113
120
  formatter: Union[Callable[[TOther], TReturn], Callable[[TArg], TReturn]],
@@ -138,24 +145,21 @@ def apply_formatters_to_dict(
138
145
  if isinstance(value, CamelModel):
139
146
  value = value.model_dump(by_alias=not unaliased)
140
147
 
141
- def get_value(key: Any, item: Any) -> Any:
148
+ def get_value(key: Any, val: Any) -> Any:
142
149
  if key not in formatters:
143
- return item
150
+ return val
144
151
  try:
145
- return formatters[key](item)
152
+ return formatters[key](val)
146
153
  except ValueError as exc:
147
154
  raise ValueError(
148
- f"Could not format invalid value {repr(item)} as field {repr(key)}"
155
+ f"Could not format invalid value {val!r} as field {key!r}"
149
156
  ) from exc
150
157
  except TypeError as exc:
151
158
  raise TypeError(
152
- f"Could not format invalid type {repr(item)} as field {repr(key)}"
159
+ f"Could not format invalid type {val!r} as field {key!r}"
153
160
  ) from exc
154
161
 
155
- return {
156
- key: get_value(key, item) if key in formatters else key
157
- for key, item in value.items()
158
- }
162
+ return {key: get_value(key, val) for key, val in value.items()}
159
163
 
160
164
 
161
165
  @return_arg_type(1)
@@ -167,9 +171,11 @@ def apply_formatter_to_array(
167
171
 
168
172
 
169
173
  def apply_one_of_formatters(
170
- formatter_condition_pairs: Tuple[Tuple[Callable[[TArg], Any], Callable[[TArg], Any]], ...],
171
- value: Any,
172
- ) -> Any:
174
+ formatter_condition_pairs: Tuple[
175
+ Tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]], ...
176
+ ],
177
+ value: TArg,
178
+ ) -> TReturn:
173
179
  for condition, formatter in formatter_condition_pairs:
174
180
  if condition(value):
175
181
  return formatter(value)
@@ -1,4 +1,5 @@
1
1
  from typing import (
2
+ TYPE_CHECKING,
2
3
  Any,
3
4
  Callable,
4
5
  Dict,
@@ -10,6 +11,7 @@ from typing import (
10
11
  Union,
11
12
  overload,
12
13
  )
14
+ from typing_extensions import TypeGuard
13
15
 
14
16
  from faster_eth_utils import (
15
17
  CamelModel,
@@ -118,41 +120,49 @@ from faster_eth_utils.toolz import (
118
120
  curry,
119
121
  )
120
122
 
123
+ if TYPE_CHECKING:
124
+ from _typeshed import SupportsBool
125
+
126
+
127
+ TArg = TypeVar("TArg")
128
+ TOther = TypeVar("TOther")
121
129
  TReturn = TypeVar("TReturn")
122
130
  TValue = TypeVar("TValue")
123
131
 
124
132
 
125
133
  @overload
126
134
  def apply_formatter_if(
127
- condition: Callable[..., bool],
128
- ) -> Callable[[Callable[..., TReturn]], Callable[[TValue], Union[TReturn, TValue]]]:
129
- pass
130
-
135
+ condition: Callable[[TArg], TypeGuard[TOther]],
136
+ ) -> Callable[[Callable[[TOther], TReturn]], Callable[[TArg], Union[TReturn, TArg]]]:
137
+ ...
131
138
 
132
139
  @overload
133
140
  def apply_formatter_if(
134
- condition: Callable[..., bool], formatter: Callable[..., TReturn]
135
- ) -> Callable[[TValue], Union[TReturn, TValue]]:
136
- pass
137
-
141
+ condition: Callable[[TArg], TypeGuard[TOther]], formatter: Callable[[TOther], TReturn]
142
+ ) -> Callable[[TArg], Union[TReturn, TArg]]:
143
+ ...
138
144
 
139
145
  @overload
140
146
  def apply_formatter_if(
141
- condition: Callable[..., bool], formatter: Callable[..., TReturn], value: TValue
142
- ) -> Union[TReturn, TValue]:
143
- pass
147
+ condition: Callable[[TArg], TypeGuard[TOther]], formatter: Callable[[TOther], TReturn], value: TArg
148
+ ) -> Union[TReturn, TArg]:
149
+ ...
144
150
 
151
+ @overload
152
+ def apply_formatter_if(
153
+ condition: Callable[[TArg], bool], formatter: Callable[[TArg], TReturn], value: TArg
154
+ ) -> Union[TReturn, TArg]:
155
+ ...
145
156
 
146
- # This is just a stub to appease mypy, it gets overwritten later
147
157
  def apply_formatter_if( # type: ignore
148
- condition: Callable[..., bool],
149
- formatter: Optional[Callable[..., TReturn]] = None,
150
- value: Optional[TValue] = None,
158
+ condition: Union[Callable[[TArg], TypeGuard[TOther]], Callable[[TArg], bool]],
159
+ formatter: Optional[Union[Callable[[TOther], TReturn], Callable[[TArg], TReturn]]] = None,
160
+ value: Optional[TArg] = None,
151
161
  ) -> Union[
152
- Callable[[Callable[..., TReturn]], Callable[[TValue], Union[TReturn, TValue]]],
153
- Callable[[TValue], Union[TReturn, TValue]],
162
+ Callable[[Callable[[TOther], TReturn]], Callable[[TArg], Union[TReturn, TArg]]],
163
+ Callable[[TArg], Union[TReturn, TArg]],
154
164
  TReturn,
155
- TValue,
165
+ TArg,
156
166
  ]:
157
167
  pass
158
168
 
@@ -160,96 +170,86 @@ def apply_formatter_if( # type: ignore
160
170
  @overload
161
171
  def apply_one_of_formatters(
162
172
  formatter_condition_pairs: Sequence[
163
- Tuple[Callable[..., bool], Callable[..., TReturn]]
173
+ Tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]]
164
174
  ],
165
- ) -> Callable[[TValue], TReturn]:
166
- ...
175
+ ) -> Callable[[TArg], TReturn]: ...
167
176
 
168
177
 
169
178
  @overload
170
179
  def apply_one_of_formatters(
171
180
  formatter_condition_pairs: Sequence[
172
- Tuple[Callable[..., bool], Callable[..., TReturn]]
181
+ Tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]]
173
182
  ],
174
- value: TValue,
175
- ) -> TReturn:
176
- ...
183
+ value: TArg,
184
+ ) -> TReturn: ...
177
185
 
178
186
 
179
187
  # This is just a stub to appease mypy, it gets overwritten later
180
- def apply_one_of_formatters( # type: ignore
188
+ def apply_one_of_formatters(
181
189
  formatter_condition_pairs: Sequence[
182
- Tuple[Callable[..., bool], Callable[..., TReturn]]
190
+ Tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]]
183
191
  ],
184
- value: Optional[TValue] = None,
185
- ) -> TReturn:
186
- ...
192
+ value: Optional[TArg] = None,
193
+ ) -> TReturn: ...
187
194
 
188
195
 
189
196
  @overload
190
197
  def hexstr_if_str(
191
198
  to_type: Callable[..., TReturn],
192
- ) -> Callable[[Union[bytes, int, str]], TReturn]:
193
- ...
199
+ ) -> Callable[[Union[bytes, int, str]], TReturn]: ...
194
200
 
195
201
 
196
202
  @overload
197
203
  def hexstr_if_str(
198
204
  to_type: Callable[..., TReturn], to_format: Union[bytes, int, str]
199
- ) -> TReturn:
200
- ...
205
+ ) -> TReturn: ...
201
206
 
202
207
 
203
208
  # This is just a stub to appease mypy, it gets overwritten later
204
209
  def hexstr_if_str( # type: ignore
205
210
  to_type: Callable[..., TReturn], to_format: Optional[Union[bytes, int, str]] = None
206
- ) -> TReturn:
207
- ...
211
+ ) -> TReturn: ...
208
212
 
209
213
 
210
214
  @overload
211
215
  def text_if_str(
212
216
  to_type: Callable[..., TReturn],
213
- ) -> Callable[[Union[bytes, int, str]], TReturn]:
214
- ...
217
+ ) -> Callable[[Union[bytes, int, str]], TReturn]: ...
215
218
 
216
219
 
217
220
  @overload
218
221
  def text_if_str(
219
222
  to_type: Callable[..., TReturn], text_or_primitive: Union[bytes, int, str]
220
- ) -> TReturn:
221
- ...
223
+ ) -> TReturn: ...
222
224
 
223
225
 
224
226
  # This is just a stub to appease mypy, it gets overwritten later
225
227
  def text_if_str( # type: ignore
226
228
  to_type: Callable[..., TReturn],
227
229
  text_or_primitive: Optional[Union[bytes, int, str]] = None,
228
- ) -> TReturn:
229
- ...
230
+ ) -> TReturn: ...
230
231
 
231
232
 
232
233
  @overload
233
234
  def apply_formatters_to_dict(
234
235
  formatters: Dict[Any, Any], unaliased: bool = False
235
- ) -> Callable[[Dict[Any, Any]], TReturn]:
236
+ ) -> Callable[[Union[Dict[Any, Any], CamelModel]], Dict[Any, Any]]:
236
237
  ...
237
238
 
238
239
 
239
240
  @overload
240
241
  def apply_formatters_to_dict(
241
- formatters: Dict[Any, Any], value: Union[Dict[Any, Any], CamelModel]
242
+ formatters: Dict[Any, Any], value: Union[Dict[Any, Any], CamelModel], unaliased: bool = False
242
243
  ) -> Dict[Any, Any]:
243
244
  ...
244
245
 
245
246
 
246
247
  # This is just a stub to appease mypy, it gets overwritten later
247
- def apply_formatters_to_dict( # type: ignore
248
+ def apply_formatters_to_dict(
248
249
  formatters: Dict[Any, Any],
249
250
  value: Optional[Union[Dict[Any, Any], CamelModel]] = None,
250
251
  unaliased: bool = False,
251
- ) -> Dict[Any, Any]:
252
- ...
252
+ ) -> Dict[Any, Any]: ...
253
253
 
254
254
 
255
255
  apply_formatter_at_index = curry(apply_formatter_at_index)
@@ -289,6 +289,7 @@ del Sequence
289
289
  del TReturn
290
290
  del TValue
291
291
  del Tuple
292
+ del TypeGuard
292
293
  del TypeVar
293
294
  del Union
294
295
  del curry
@@ -0,0 +1,119 @@
1
+ import functools
2
+ from typing import (
3
+ Any,
4
+ Callable,
5
+ Dict,
6
+ Final,
7
+ Generic,
8
+ Optional,
9
+ Tuple,
10
+ Type,
11
+ TypeVar,
12
+ Union,
13
+ final,
14
+ )
15
+
16
+ from typing_extensions import Concatenate, ParamSpec
17
+
18
+ P = ParamSpec("P")
19
+
20
+ T = TypeVar("T")
21
+
22
+ TInstance = TypeVar("TInstance", bound=object)
23
+ """A TypeVar representing an instance that a method can bind to."""
24
+
25
+
26
+ @final
27
+ class combomethod(Generic[TInstance, P, T]):
28
+ def __init__(
29
+ self, method: Callable[Concatenate[Union[TInstance, Type[TInstance]], P], T]
30
+ ) -> None:
31
+ self.method: Final = method
32
+
33
+ def __repr__(self) -> str:
34
+ return f"combomethod({self.method})"
35
+
36
+ def __get__(
37
+ self,
38
+ obj: Optional[TInstance],
39
+ objtype: Type[TInstance],
40
+ ) -> Callable[P, T]:
41
+
42
+ @functools.wraps(self.method)
43
+ def _wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
44
+ if obj is not None:
45
+ return self.method(obj, *args, **kwargs)
46
+ else:
47
+ return self.method(objtype, *args, **kwargs) # type: ignore [arg-type]
48
+
49
+ return _wrapper
50
+
51
+
52
+ _return_arg_type_deco_cache: Final[
53
+ Dict[int, Callable[[Callable[P, T]], Callable[P, Any]]]
54
+ ] = {}
55
+ # No need to hold so many unique instances in memory
56
+
57
+
58
+ def return_arg_type(at_position: int) -> Callable[[Callable[P, T]], Callable[P, Any]]:
59
+ """
60
+ Wrap the return value with the result of `type(args[at_position])`.
61
+ """
62
+ if deco := _return_arg_type_deco_cache.get(at_position):
63
+ return deco
64
+
65
+ def decorator(to_wrap: Callable[P, Any]) -> Callable[P, Any]:
66
+ @functools.wraps(to_wrap)
67
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> Any:
68
+ result = to_wrap(*args, **kwargs)
69
+ ReturnType = type(args[at_position])
70
+ return ReturnType(result) # type: ignore [call-arg]
71
+
72
+ return wrapper
73
+
74
+ _return_arg_type_deco_cache[at_position] = decorator
75
+
76
+ return decorator
77
+
78
+
79
+ ExcType = Type[BaseException]
80
+
81
+ ReplaceExceptionsCache = Dict[
82
+ Tuple[Tuple[ExcType, ExcType], ...],
83
+ Callable[[Callable[P, T]], Callable[P, T]],
84
+ ]
85
+
86
+ _replace_exceptions_deco_cache: Final[ReplaceExceptionsCache[..., Any]] = {}
87
+ # No need to hold so many unique instances in memory
88
+
89
+
90
+ def replace_exceptions(
91
+ old_to_new_exceptions: Dict[ExcType, ExcType],
92
+ ) -> Callable[[Callable[P, T]], Callable[P, T]]:
93
+ """
94
+ Replaces old exceptions with new exceptions to be raised in their place.
95
+ """
96
+ cache_key = tuple(old_to_new_exceptions.items())
97
+ if deco := _replace_exceptions_deco_cache.get(cache_key):
98
+ return deco
99
+
100
+ old_exceptions = tuple(old_to_new_exceptions)
101
+
102
+ def decorator(to_wrap: Callable[P, T]) -> Callable[P, T]:
103
+ @functools.wraps(to_wrap)
104
+ def wrapped(*args: P.args, **kwargs: P.kwargs) -> T:
105
+ try:
106
+ return to_wrap(*args, **kwargs)
107
+ except old_exceptions as err:
108
+ try:
109
+ raise old_to_new_exceptions[type(err)](err) from err
110
+ except KeyError:
111
+ raise TypeError(
112
+ f"could not look up new exception to use for {repr(err)}"
113
+ ) from err
114
+
115
+ return wrapped
116
+
117
+ _replace_exceptions_deco_cache[cache_key] = decorator
118
+
119
+ return decorator
@@ -12,6 +12,7 @@ from typing import (
12
12
  TypeVar,
13
13
  Union,
14
14
  cast,
15
+ overload,
15
16
  )
16
17
 
17
18
  from .toolz import (
@@ -53,8 +54,7 @@ def setup_DEBUG2_logging() -> None:
53
54
  """
54
55
  if not hasattr(logging, "DEBUG2"):
55
56
  logging.addLevelName(DEBUG2_LEVEL_NUM, "DEBUG2")
56
- logging.DEBUG2 = DEBUG2_LEVEL_NUM # type: ignore
57
-
57
+ logging.DEBUG2 = DEBUG2_LEVEL_NUM # type: ignore [attr-defined]
58
58
 
59
59
  @contextlib.contextmanager
60
60
  def _use_logger_class(logger_class: Type[logging.Logger]) -> Iterator[None]:
@@ -66,24 +66,26 @@ def _use_logger_class(logger_class: Type[logging.Logger]) -> Iterator[None]:
66
66
  logging.setLoggerClass(original_logger_class)
67
67
 
68
68
 
69
- def get_logger(name: str, logger_class: Union[Type[TLogger], None] = None) -> TLogger:
69
+ @overload
70
+ def get_logger(name: str, logger_class: Type[TLogger]) -> TLogger: ...
71
+ @overload
72
+ def get_logger(name: str, logger_class: None = None) -> logging.Logger: ...
73
+ def get_logger(name: str, logger_class: Union[Type[TLogger], None] = None) -> Union[TLogger, logging.Logger]:
70
74
  if logger_class is None:
75
+ return logging.getLogger(name)
76
+
77
+ with _use_logger_class(logger_class):
78
+ # The logging module caches logger instances. The following code
79
+ # ensures that if there is a cached instance that we don't
80
+ # accidentally return the incorrect logger type because the logging
81
+ # module does not *update* the cached instance in the event that
82
+ # the global logging class changes.
83
+ manager = logging.Logger.manager
84
+ logger_dict = manager.loggerDict
85
+ cached_logger = logger_dict.get(name)
86
+ if cached_logger is not None and type(cached_logger) is not logger_class:
87
+ del logger_dict[name]
71
88
  return cast(TLogger, logging.getLogger(name))
72
- else:
73
- with _use_logger_class(logger_class):
74
- # The logging module caches logger instances. The following code
75
- # ensures that if there is a cached instance that we don't
76
- # accidentally return the incorrect logger type because the logging
77
- # module does not *update* the cached instance in the event that
78
- # the global logging class changes.
79
- #
80
- # types ignored b/c mypy doesn't identify presence of
81
- # manager on logging.Logger
82
- manager = logging.Logger.manager
83
- if name in manager.loggerDict:
84
- if type(manager.loggerDict[name]) is not logger_class:
85
- del manager.loggerDict[name]
86
- return cast(TLogger, logging.getLogger(name))
87
89
 
88
90
 
89
91
  def get_extended_debug_logger(name: str) -> ExtendedDebugLogger:
@@ -115,9 +117,8 @@ class HasLoggerMeta(type):
115
117
  return super().__new__(mcls, name, bases, namespace)
116
118
  if "__qualname__" not in namespace:
117
119
  raise AttributeError("Missing __qualname__")
118
-
119
- with _use_logger_class(mcls.logger_class):
120
- logger = logging.getLogger(namespace["__qualname__"])
120
+
121
+ logger = get_logger(namespace["__qualname__"], mcls.logger_class)
121
122
 
122
123
  return super().__new__(mcls, name, bases, assoc(namespace, "logger", logger))
123
124
 
@@ -141,5 +142,5 @@ class HasLogger(metaclass=HasLoggerMeta):
141
142
  HasExtendedDebugLoggerMeta = HasLoggerMeta.replace_logger_class(ExtendedDebugLogger)
142
143
 
143
144
 
144
- class HasExtendedDebugLogger(metaclass=HasExtendedDebugLoggerMeta): # type: ignore
145
+ class HasExtendedDebugLogger(metaclass=HasExtendedDebugLoggerMeta): # type: ignore [metaclass,misc]
145
146
  logger: ExtendedDebugLogger
@@ -45,11 +45,11 @@ def is_boolean(value: Any) -> TypeGuard[bool]:
45
45
 
46
46
 
47
47
  def is_dict(obj: Any) -> TypeGuard[collections.abc.Mapping[Any, Any]]:
48
- return isinstance(obj, Mapping)
48
+ return isinstance(obj, dict) or isinstance(obj, Mapping)
49
49
 
50
50
 
51
51
  def is_list_like(obj: Any) -> TypeGuard[collections.abc.Sequence[Any]]:
52
- return not is_string(obj) and isinstance(obj, Sequence)
52
+ return isinstance(obj, (list, tuple)) or not is_string(obj) and isinstance(obj, Sequence)
53
53
 
54
54
 
55
55
  def is_list(obj: Any) -> TypeGuard[List[Any]]:
@@ -1,14 +1,21 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: faster-eth-utils
3
- Version: 5.3.12
3
+ Version: 5.3.16
4
4
  Summary: A fork of eth-utils: Common utility functions for python code that interacts with Ethereum, implemented in C
5
- Home-page: https://github.com/BobTheBuidler/eth-utils
5
+ Home-page: https://github.com/BobTheBuidler/faster-eth-utils
6
6
  Author: The Ethereum Foundation
7
7
  Author-email: snakecharmers@ethereum.org
8
8
  License: MIT
9
+ Project-URL: Documentation, https://eth-utils.readthedocs.io/en/stable/
10
+ Project-URL: Release Notes, https://github.com/BobTheBuidler/faster-eth-utils/releases
11
+ Project-URL: Issues, https://github.com/BobTheBuidler/faster-eth-utils/issues
12
+ Project-URL: Source - Precompiled (.py), https://github.com/BobTheBuidler/faster-eth-utils/tree/master/faster_eth_utils
13
+ Project-URL: Source - Compiled (.c), https://github.com/BobTheBuidler/faster-eth-utils/tree/master/build
14
+ Project-URL: Benchmarks, https://github.com/BobTheBuidler/faster-eth-utils/tree/master/benchmarks
15
+ Project-URL: Benchmarks - Results, https://github.com/BobTheBuidler/faster-eth-utils/tree/master/benchmarks/results
16
+ Project-URL: Original, https://github.com/ethereum/eth-utils
9
17
  Keywords: ethereum
10
18
  Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: MIT License
12
19
  Classifier: Natural Language :: English
13
20
  Classifier: Programming Language :: Python :: 3
14
21
  Classifier: Programming Language :: Python :: 3.8
@@ -45,7 +52,6 @@ Requires-Dist: towncrier<26,>=24; extra == "dev"
45
52
  Requires-Dist: hypothesis>=4.43.0; extra == "dev"
46
53
  Requires-Dist: mypy==1.18.2; extra == "dev"
47
54
  Requires-Dist: pytest>=7.0.0; extra == "dev"
48
- Requires-Dist: pytest-codspeed>=2.0.0; extra == "dev"
49
55
  Requires-Dist: pytest-xdist>=2.4.0; extra == "dev"
50
56
  Provides-Extra: docs
51
57
  Requires-Dist: sphinx>=6.0.0; extra == "docs"
@@ -56,8 +62,10 @@ Provides-Extra: test
56
62
  Requires-Dist: hypothesis>=4.43.0; extra == "test"
57
63
  Requires-Dist: mypy==1.18.2; extra == "test"
58
64
  Requires-Dist: pytest>=7.0.0; extra == "test"
59
- Requires-Dist: pytest-codspeed>=2.0.0; extra == "test"
60
65
  Requires-Dist: pytest-xdist>=2.4.0; extra == "test"
66
+ Provides-Extra: codspeed
67
+ Requires-Dist: pytest>=7.0.0; extra == "codspeed"
68
+ Requires-Dist: pytest-codspeed<4.3,>=4.2; extra == "codspeed"
61
69
  Dynamic: author
62
70
  Dynamic: author-email
63
71
  Dynamic: classifier
@@ -67,6 +75,7 @@ Dynamic: home-page
67
75
  Dynamic: keywords
68
76
  Dynamic: license
69
77
  Dynamic: license-file
78
+ Dynamic: project-url
70
79
  Dynamic: provides-extra
71
80
  Dynamic: requires-dist
72
81
  Dynamic: requires-python
@@ -10,6 +10,10 @@ cytoolz>=0.10.1
10
10
  [:implementation_name == "pypy"]
11
11
  toolz>0.8.2
12
12
 
13
+ [codspeed]
14
+ pytest>=7.0.0
15
+ pytest-codspeed<4.3,>=4.2
16
+
13
17
  [dev]
14
18
  build>=0.9.0
15
19
  bump_my_version>=0.19.0
@@ -26,7 +30,6 @@ sphinx_rtd_theme>=1.0.0
26
30
  towncrier<26,>=24
27
31
  hypothesis>=4.43.0
28
32
  pytest>=7.0.0
29
- pytest-codspeed>=2.0.0
30
33
  pytest-xdist>=2.4.0
31
34
 
32
35
  [docs]
@@ -39,5 +42,4 @@ towncrier<26,>=24
39
42
  hypothesis>=4.43.0
40
43
  mypy==1.18.2
41
44
  pytest>=7.0.0
42
- pytest-codspeed>=2.0.0
43
45
  pytest-xdist>=2.4.0
@@ -2,13 +2,14 @@
2
2
  requires = [
3
3
  "setuptools",
4
4
  "wheel",
5
- "mypy[mypyc]>=1.14.1,<1.18.3",
6
- "cchecksum>=0.0.3",
7
- "eth-hash>=0.3.1",
8
- "eth-typing>=5.0.0",
9
- # puccinialin (installed with faster-eth-utils) is unable to install for
5
+ "mypy[mypyc]==1.14.1; python_version == '3.8'",
6
+ "mypy[mypyc]==1.18.2; python_version != '3.8'",
7
+ "cchecksum==0.3.3",
8
+ "eth-hash==0.7.1",
9
+ "eth-typing==5.2.1",
10
+ # puccinialin (installed with eth-utils) is unable to install for
10
11
  # Python3.14 on 32-bit manylinux or on 32-bit musllinux for any Python version
11
- "eth-utils>=5.2.0,<6; platform_system != 'Linux' or platform_machine != 'i686'",
12
+ "eth-utils==5.3.1; platform_system != 'Linux' or platform_machine != 'i686'",
12
13
  ]
13
14
  build-backend = "setuptools.build_meta"
14
15
 
@@ -139,7 +140,7 @@ name = "Removals"
139
140
  showcontent = true
140
141
 
141
142
  [tool.bumpversion]
142
- current_version = "5.3.12"
143
+ current_version = "5.3.16"
143
144
  parse = """
144
145
  (?P<major>\\d+)
145
146
  \\.(?P<minor>\\d+)
@@ -46,7 +46,6 @@ else:
46
46
  "--install-types",
47
47
  "--disable-error-code=attr-defined",
48
48
  "--disable-error-code=comparison-overlap",
49
- "--disable-error-code=typeddict-item",
50
49
  "--disable-error-code=no-any-return",
51
50
  "--disable-error-code=misc",
52
51
  "--disable-error-code=unused-ignore",
@@ -55,6 +54,7 @@ else:
55
54
  )
56
55
 
57
56
  MYPY_REQUIREMENT = f"mypy=={'1.14.1' if sys.version_info < (3, 9) else '1.18.2'}"
57
+ PYTEST_REQUIREMENT = "pytest>=7.0.0"
58
58
 
59
59
  extras_require = {
60
60
  "dev": [
@@ -77,10 +77,13 @@ extras_require = {
77
77
  "test": [
78
78
  "hypothesis>=4.43.0",
79
79
  MYPY_REQUIREMENT,
80
- "pytest>=7.0.0",
81
- "pytest-codspeed>=2.0.0",
80
+ PYTEST_REQUIREMENT,
82
81
  "pytest-xdist>=2.4.0",
83
82
  ],
83
+ "codspeed": [
84
+ PYTEST_REQUIREMENT,
85
+ "pytest-codspeed>=4.2,<4.3",
86
+ ],
84
87
  }
85
88
 
86
89
  extras_require["dev"] = (
@@ -95,7 +98,7 @@ with open("./README.md") as readme:
95
98
  setup(
96
99
  name="faster-eth-utils",
97
100
  # *IMPORTANT*: Don't manually change the version here. Use `make bump`, as described in readme
98
- version="5.3.12",
101
+ version="5.3.16",
99
102
  description=(
100
103
  """A fork of eth-utils: Common utility functions for python code that interacts with Ethereum, implemented in C"""
101
104
  ),
@@ -103,7 +106,17 @@ setup(
103
106
  long_description_content_type="text/markdown",
104
107
  author="The Ethereum Foundation",
105
108
  author_email="snakecharmers@ethereum.org",
106
- url="https://github.com/BobTheBuidler/eth-utils",
109
+ url="https://github.com/BobTheBuidler/faster-eth-utils",
110
+ project_urls={
111
+ "Documentation": "https://eth-utils.readthedocs.io/en/stable/",
112
+ "Release Notes": "https://github.com/BobTheBuidler/faster-eth-utils/releases",
113
+ "Issues": "https://github.com/BobTheBuidler/faster-eth-utils/issues",
114
+ "Source - Precompiled (.py)": "https://github.com/BobTheBuidler/faster-eth-utils/tree/master/faster_eth_utils",
115
+ "Source - Compiled (.c)": "https://github.com/BobTheBuidler/faster-eth-utils/tree/master/build",
116
+ "Benchmarks": "https://github.com/BobTheBuidler/faster-eth-utils/tree/master/benchmarks",
117
+ "Benchmarks - Results": "https://github.com/BobTheBuidler/faster-eth-utils/tree/master/benchmarks/results",
118
+ "Original": "https://github.com/ethereum/eth-utils",
119
+ },
107
120
  include_package_data=True,
108
121
  install_requires=[
109
122
  "cchecksum>=0.0.3",
@@ -118,6 +131,7 @@ setup(
118
131
  extras_require=extras_require,
119
132
  py_modules=["eth_utils"],
120
133
  license="MIT",
134
+ license_files=["LICENSE"],
121
135
  zip_safe=False,
122
136
  keywords="ethereum",
123
137
  packages=find_packages(exclude=["scripts", "scripts.*", "tests", "tests.*"]),
@@ -125,7 +139,6 @@ setup(
125
139
  package_data={"faster_eth_utils": ["py.typed"]},
126
140
  classifiers=[
127
141
  "Intended Audience :: Developers",
128
- "License :: OSI Approved :: MIT License",
129
142
  "Natural Language :: English",
130
143
  "Programming Language :: Python :: 3",
131
144
  "Programming Language :: Python :: 3.8",
@@ -1,79 +0,0 @@
1
- import functools
2
- import itertools
3
- import os
4
- from typing import (
5
- Any,
6
- Callable,
7
- Dict,
8
- Optional,
9
- Type,
10
- TypeVar,
11
- final,
12
- )
13
-
14
- from .types import (
15
- is_text,
16
- )
17
-
18
- T = TypeVar("T")
19
-
20
-
21
- @final
22
- class combomethod:
23
- def __init__(self, method: Callable[..., Any]) -> None:
24
- self.method = method
25
-
26
- def __get__(
27
- self, obj: Optional[T] = None, objtype: Optional[Type[T]] = None
28
- ) -> Callable[..., Any]:
29
- @functools.wraps(self.method)
30
- def _wrapper(*args: Any, **kwargs: Any) -> Any:
31
- if obj is not None:
32
- return self.method(obj, *args, **kwargs)
33
- else:
34
- return self.method(objtype, *args, **kwargs)
35
-
36
- return _wrapper
37
-
38
-
39
- def return_arg_type(at_position: int) -> Callable[..., Callable[..., T]]:
40
- """
41
- Wrap the return value with the result of `type(args[at_position])`.
42
- """
43
-
44
- def decorator(to_wrap: Callable[..., Any]) -> Callable[..., T]:
45
- @functools.wraps(to_wrap)
46
- def wrapper(*args: Any, **kwargs: Any) -> T: # type: ignore
47
- result = to_wrap(*args, **kwargs)
48
- ReturnType = type(args[at_position])
49
- return ReturnType(result) # type: ignore
50
-
51
- return wrapper
52
-
53
- return decorator
54
-
55
-
56
- def replace_exceptions(
57
- old_to_new_exceptions: Dict[Type[BaseException], Type[BaseException]]
58
- ) -> Callable[[Callable[..., T]], Callable[..., T]]:
59
- """
60
- Replaces old exceptions with new exceptions to be raised in their place.
61
- """
62
- old_exceptions = tuple(old_to_new_exceptions.keys())
63
-
64
- def decorator(to_wrap: Callable[..., T]) -> Callable[..., T]:
65
- @functools.wraps(to_wrap)
66
- def wrapped(*args: Any, **kwargs: Any) -> T:
67
- try:
68
- return to_wrap(*args, **kwargs)
69
- except old_exceptions as err:
70
- try:
71
- raise old_to_new_exceptions[type(err)](err) from err
72
- except KeyError:
73
- raise TypeError(
74
- f"could not look up new exception to use for {repr(err)}"
75
- ) from err
76
-
77
- return wrapped
78
-
79
- return decorator