faster-eth-utils 2.3.1__cp311-cp311-win32.whl → 5.3.19__cp311-cp311-win32.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 faster-eth-utils might be problematic. Click here for more details.

Files changed (53) hide show
  1. faster_eth_utils/__init__.py +54 -17
  2. faster_eth_utils/__json/eth_networks.json +1 -0
  3. faster_eth_utils/__main__.py +3 -1
  4. faster_eth_utils/abi.cp311-win32.pyd +0 -0
  5. faster_eth_utils/abi.py +819 -37
  6. faster_eth_utils/address.cp311-win32.pyd +0 -0
  7. faster_eth_utils/address.py +57 -62
  8. faster_eth_utils/applicators.cp311-win32.pyd +0 -0
  9. faster_eth_utils/applicators.py +138 -70
  10. faster_eth_utils/conversions.cp311-win32.pyd +0 -0
  11. faster_eth_utils/conversions.py +54 -25
  12. faster_eth_utils/crypto.cp311-win32.pyd +0 -0
  13. faster_eth_utils/crypto.py +15 -5
  14. faster_eth_utils/currency.cp311-win32.pyd +0 -0
  15. faster_eth_utils/currency.py +70 -32
  16. faster_eth_utils/curried/__init__.py +107 -77
  17. faster_eth_utils/debug.cp311-win32.pyd +0 -0
  18. faster_eth_utils/debug.py +3 -3
  19. faster_eth_utils/decorators.cp311-win32.pyd +0 -0
  20. faster_eth_utils/decorators.py +73 -20
  21. faster_eth_utils/encoding.cp311-win32.pyd +0 -0
  22. faster_eth_utils/exceptions.cp311-win32.pyd +0 -0
  23. faster_eth_utils/exceptions.py +8 -3
  24. faster_eth_utils/functional.cp311-win32.pyd +0 -0
  25. faster_eth_utils/functional.py +41 -25
  26. faster_eth_utils/hexadecimal.cp311-win32.pyd +0 -0
  27. faster_eth_utils/hexadecimal.py +36 -24
  28. faster_eth_utils/humanize.cp311-win32.pyd +0 -0
  29. faster_eth_utils/humanize.py +46 -18
  30. faster_eth_utils/logging.py +43 -48
  31. faster_eth_utils/module_loading.cp311-win32.pyd +0 -0
  32. faster_eth_utils/module_loading.py +8 -7
  33. faster_eth_utils/network.cp311-win32.pyd +0 -0
  34. faster_eth_utils/network.py +25 -13
  35. faster_eth_utils/numeric.cp311-win32.pyd +0 -0
  36. faster_eth_utils/numeric.py +11 -4
  37. faster_eth_utils/pydantic.py +101 -0
  38. faster_eth_utils/toolz.cp311-win32.pyd +0 -0
  39. faster_eth_utils/toolz.py +82 -152
  40. faster_eth_utils/types.cp311-win32.pyd +0 -0
  41. faster_eth_utils/types.py +37 -21
  42. faster_eth_utils/typing/misc.py +3 -1
  43. faster_eth_utils/units.cp311-win32.pyd +0 -0
  44. faster_eth_utils-5.3.19.dist-info/METADATA +193 -0
  45. faster_eth_utils-5.3.19.dist-info/RECORD +53 -0
  46. {faster_eth_utils-2.3.1.dist-info → faster_eth_utils-5.3.19.dist-info}/licenses/LICENSE +1 -1
  47. faster_eth_utils-5.3.19.dist-info/top_level.txt +3 -0
  48. faster_eth_utils__mypyc.cp311-win32.pyd +0 -0
  49. bce0bfc64ce5e845ec4a__mypyc.cp311-win32.pyd +0 -0
  50. faster_eth_utils-2.3.1.dist-info/METADATA +0 -160
  51. faster_eth_utils-2.3.1.dist-info/RECORD +0 -45
  52. faster_eth_utils-2.3.1.dist-info/top_level.txt +0 -3
  53. {faster_eth_utils-2.3.1.dist-info → faster_eth_utils-5.3.19.dist-info}/WHEEL +0 -0
@@ -1,9 +1,20 @@
1
1
  import decimal
2
- from decimal import localcontext
3
- from typing import Final, Union, final
4
-
5
- from .types import is_integer, is_string
6
- from .units import units
2
+ from decimal import (
3
+ localcontext,
4
+ )
5
+ from typing import (
6
+ Final,
7
+ Union,
8
+ final,
9
+ )
10
+
11
+ from .types import (
12
+ is_integer,
13
+ is_string,
14
+ )
15
+ from .units import (
16
+ units,
17
+ )
7
18
 
8
19
 
9
20
  @final
@@ -36,23 +47,15 @@ class denoms:
36
47
  MIN_WEI: Final = 0
37
48
  MAX_WEI: Final = 2**256 - 1
38
49
 
50
+ _NumberType = Union[int, float, str, decimal.Decimal]
39
51
 
40
- def from_wei(number: int, unit: str) -> Union[int, decimal.Decimal]:
41
- """
42
- Takes a number of wei and converts it to any other ether unit.
43
- """
44
- if unit.lower() not in units:
45
- raise ValueError(
46
- "Unknown unit. Must be one of {0}".format("/".join(units.keys()))
47
- )
48
52
 
53
+ def _from_wei(number: int, unit_value: decimal.Decimal) -> Union[int, decimal.Decimal]:
49
54
  if number == 0:
50
55
  return 0
51
56
 
52
57
  if number < MIN_WEI or number > MAX_WEI:
53
- raise ValueError("value must be between 1 and 2**256 - 1")
54
-
55
- unit_value = units[unit.lower()]
58
+ raise ValueError("value must be between 0 and 2**256 - 1")
56
59
 
57
60
  with localcontext() as ctx:
58
61
  ctx.prec = 999
@@ -62,35 +65,26 @@ def from_wei(number: int, unit: str) -> Union[int, decimal.Decimal]:
62
65
  return result_value
63
66
 
64
67
 
65
- def to_wei(number: Union[int, float, str, decimal.Decimal], unit: str) -> int:
66
- """
67
- Takes a number of a unit and converts it to wei.
68
- """
69
- if unit.lower() not in units:
70
- raise ValueError(
71
- "Unknown unit. Must be one of {0}".format("/".join(units.keys()))
72
- )
73
-
68
+ def _to_wei(number: _NumberType, unit_value: decimal.Decimal) -> int:
74
69
  if is_integer(number) or is_string(number):
75
- d_number = decimal.Decimal(value=number)
70
+ d_number = decimal.Decimal(value=number) # type: ignore [arg-type]
76
71
  elif isinstance(number, float):
77
72
  d_number = decimal.Decimal(value=str(number))
78
73
  elif isinstance(number, decimal.Decimal):
79
74
  d_number = number
80
75
  else:
81
- raise TypeError("Unsupported type. Must be one of integer, float, or string")
82
-
83
- s_number = str(number)
84
- unit_value = units[unit.lower()]
76
+ raise TypeError("Unsupported type. Must be one of integer, float, or string")
85
77
 
86
78
  if d_number == decimal.Decimal(0):
87
79
  return 0
88
80
 
81
+ s_number = str(number)
82
+
89
83
  if d_number < 1 and "." in s_number:
90
84
  with localcontext() as ctx:
91
85
  multiplier = len(s_number) - s_number.index(".") - 1
92
86
  ctx.prec = multiplier
93
- d_number = decimal.Decimal(value=number, context=ctx) * 10**multiplier
87
+ d_number = decimal.Decimal(value=number, context=ctx) * 10**multiplier # type: ignore [arg-type]
94
88
  unit_value /= 10**multiplier
95
89
 
96
90
  with localcontext() as ctx:
@@ -98,6 +92,50 @@ def to_wei(number: Union[int, float, str, decimal.Decimal], unit: str) -> int:
98
92
  result_value = decimal.Decimal(value=d_number, context=ctx) * unit_value
99
93
 
100
94
  if result_value < MIN_WEI or result_value > MAX_WEI:
101
- raise ValueError("Resulting wei value must be between 1 and 2**256 - 1")
95
+ raise ValueError("Resulting wei value must be between 0 and 2**256 - 1")
102
96
 
103
97
  return int(result_value)
98
+
99
+
100
+ def from_wei(number: int, unit: str) -> Union[int, decimal.Decimal]:
101
+ """
102
+ Takes a number of wei and converts it to any other ether unit.
103
+ """
104
+ if unit.lower() not in units:
105
+ raise ValueError(f"Unknown unit. Must be one of {'/'.join(units.keys())}")
106
+
107
+ unit_value = units[unit.lower()]
108
+
109
+ return _from_wei(number, unit_value)
110
+
111
+
112
+ def to_wei(number: _NumberType, unit: str) -> int:
113
+ """
114
+ Takes a number of a unit and converts it to wei.
115
+ """
116
+ if unit.lower() not in units:
117
+ raise ValueError(f"Unknown unit. Must be one of {'/'.join(units.keys())}")
118
+
119
+ unit_value = units[unit.lower()]
120
+
121
+ return _to_wei(number, unit_value)
122
+
123
+
124
+ def from_wei_decimals(number: int, decimals: int) -> Union[int, decimal.Decimal]:
125
+ """
126
+ Takes a number of wei and converts it to a decimal with the specified
127
+ number of decimals.
128
+ """
129
+ unit_value = decimal.Decimal(10) ** decimal.Decimal(value=decimals)
130
+
131
+ return _from_wei(number, unit_value)
132
+
133
+
134
+ def to_wei_decimals(number: _NumberType, decimals: int) -> int:
135
+ """
136
+ Takes a number of a unit and converts it to wei with the specified
137
+ number of decimals.
138
+ """
139
+ unit_value = decimal.Decimal(10) ** decimal.Decimal(value=decimals)
140
+
141
+ return _to_wei(number, unit_value)
@@ -1,5 +1,6 @@
1
- # flake8: noqa
1
+ import sys
2
2
  from typing import (
3
+ TYPE_CHECKING,
3
4
  Any,
4
5
  Callable,
5
6
  Dict,
@@ -11,8 +12,10 @@ from typing import (
11
12
  Union,
12
13
  overload,
13
14
  )
15
+ from typing_extensions import TypeGuard
14
16
 
15
17
  from faster_eth_utils import (
18
+ CamelModel,
16
19
  ExtendedDebugLogger,
17
20
  HasExtendedDebugLogger,
18
21
  HasExtendedDebugLoggerMeta,
@@ -20,13 +23,19 @@ from faster_eth_utils import (
20
23
  HasLoggerMeta,
21
24
  Network,
22
25
  ValidationError,
26
+ abi_to_signature,
23
27
  add_0x_prefix,
24
28
  apply_formatter_at_index,
25
- )
26
- from faster_eth_utils import (
29
+ apply_formatter_if as non_curried_apply_formatter_if,
30
+ apply_formatter_to_array,
31
+ apply_formatters_to_dict as non_curried_apply_formatters_to_dict,
32
+ apply_formatters_to_sequence,
33
+ apply_key_map,
34
+ apply_one_of_formatters as non_curried_apply_one_of_formatters,
27
35
  apply_to_return_value,
28
36
  big_endian_to_int,
29
37
  clamp,
38
+ collapse_if_tuple,
30
39
  combine_argument_formatters,
31
40
  combomethod,
32
41
  decode_hex,
@@ -34,16 +43,27 @@ from faster_eth_utils import (
34
43
  encode_hex,
35
44
  event_abi_to_log_topic,
36
45
  event_signature_to_log_topic,
46
+ filter_abi_by_name,
47
+ filter_abi_by_type,
37
48
  flatten_return,
38
49
  from_wei,
50
+ from_wei_decimals,
39
51
  function_abi_to_4byte_selector,
40
52
  function_signature_to_4byte_selector,
53
+ get_abi_input_names,
54
+ get_abi_input_types,
55
+ get_abi_output_names,
56
+ get_abi_output_types,
57
+ get_aligned_abi_inputs,
58
+ get_all_event_abis,
59
+ get_all_function_abis,
41
60
  get_extended_debug_logger,
42
61
  get_logger,
43
- )
44
- from faster_eth_utils import (
62
+ get_normalized_abi_inputs,
63
+ hexstr_if_str as non_curried_hexstr_if_str,
45
64
  humanize_bytes,
46
65
  humanize_hash,
66
+ humanize_hexstr,
47
67
  humanize_integer_sequence,
48
68
  humanize_ipfs_uri,
49
69
  humanize_seconds,
@@ -81,8 +101,7 @@ from faster_eth_utils import (
81
101
  setup_DEBUG2_logging,
82
102
  short_name_from_chain_id,
83
103
  sort_return,
84
- )
85
- from faster_eth_utils import (
104
+ text_if_str as non_curried_text_if_str,
86
105
  to_bytes,
87
106
  to_canonical_address,
88
107
  to_checksum_address,
@@ -96,166 +115,176 @@ from faster_eth_utils import (
96
115
  to_text,
97
116
  to_tuple,
98
117
  to_wei,
118
+ to_wei_decimals,
99
119
  )
100
- from faster_eth_utils import apply_formatter_if as non_curried_apply_formatter_if
101
- from faster_eth_utils import apply_formatter_to_array
102
- from faster_eth_utils import apply_formatters_to_dict as non_curried_apply_formatters_to_dict
103
- from faster_eth_utils import apply_formatters_to_sequence, apply_key_map
104
- from faster_eth_utils import apply_one_of_formatters as non_curried_apply_one_of_formatters
105
- from faster_eth_utils import hexstr_if_str as non_curried_hexstr_if_str
106
- from faster_eth_utils import text_if_str as non_curried_text_if_str
107
- from faster_eth_utils.toolz import curry
120
+ from faster_eth_utils.toolz import (
121
+ curry,
122
+ )
123
+
124
+ if TYPE_CHECKING:
125
+ if sys.version_info >= (3, 9):
126
+ from _typeshed import SupportsBool
127
+ # We have to sacrifice a little bit of specificity on dinosaur Python3.8
128
+ else:
129
+ SupportsBool = Any
108
130
 
131
+
132
+ TArg = TypeVar("TArg")
133
+ TOther = TypeVar("TOther")
109
134
  TReturn = TypeVar("TReturn")
110
135
  TValue = TypeVar("TValue")
111
136
 
112
137
 
113
138
  @overload
114
139
  def apply_formatter_if(
115
- condition: Callable[..., bool]
116
- ) -> Callable[[Callable[..., TReturn]], Callable[[TValue], Union[TReturn, TValue]]]:
140
+ condition: Callable[[TArg], TypeGuard[TOther]],
141
+ ) -> Callable[[Callable[[TOther], TReturn]], Callable[[TArg], Union[TReturn, TArg]]]:
117
142
  ...
118
143
 
119
-
120
144
  @overload
121
145
  def apply_formatter_if(
122
- condition: Callable[..., bool], formatter: Callable[..., TReturn]
123
- ) -> Callable[[TValue], Union[TReturn, TValue]]:
146
+ condition: Callable[[TArg], TypeGuard[TOther]], formatter: Callable[[TOther], TReturn]
147
+ ) -> Callable[[TArg], Union[TReturn, TArg]]:
124
148
  ...
125
149
 
126
-
127
150
  @overload
128
151
  def apply_formatter_if(
129
- condition: Callable[..., bool], formatter: Callable[..., TReturn], value: TValue
130
- ) -> Union[TReturn, TValue]:
152
+ condition: Callable[[TArg], TypeGuard[TOther]], formatter: Callable[[TOther], TReturn], value: TArg
153
+ ) -> Union[TReturn, TArg]:
131
154
  ...
132
155
 
133
-
134
- # This is just a stub to appease mypy, it gets overwritten later
156
+ @overload
135
157
  def apply_formatter_if(
136
- condition: Callable[..., bool],
137
- formatter: Callable[..., TReturn] = None,
138
- value: TValue = None,
158
+ condition: Callable[[TArg], bool], formatter: Callable[[TArg], TReturn], value: TArg
159
+ ) -> Union[TReturn, TArg]:
160
+ ...
161
+
162
+ def apply_formatter_if( # type: ignore
163
+ condition: Union[Callable[[TArg], TypeGuard[TOther]], Callable[[TArg], bool]],
164
+ formatter: Optional[Union[Callable[[TOther], TReturn], Callable[[TArg], TReturn]]] = None,
165
+ value: Optional[TArg] = None,
139
166
  ) -> Union[
140
- Callable[[Callable[..., TReturn]], Callable[[TValue], Union[TReturn, TValue]]],
141
- Callable[[TValue], Union[TReturn, TValue]],
167
+ Callable[[Callable[[TOther], TReturn]], Callable[[TArg], Union[TReturn, TArg]]],
168
+ Callable[[TArg], Union[TReturn, TArg]],
142
169
  TReturn,
143
- TValue,
170
+ TArg,
144
171
  ]:
145
- ...
172
+ pass
146
173
 
147
174
 
148
175
  @overload
149
176
  def apply_one_of_formatters(
150
177
  formatter_condition_pairs: Sequence[
151
- Tuple[Callable[..., bool], Callable[..., TReturn]]
152
- ]
153
- ) -> Callable[[TValue], TReturn]:
154
- ...
178
+ Tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]]
179
+ ],
180
+ ) -> Callable[[TArg], TReturn]: ...
155
181
 
156
182
 
157
183
  @overload
158
184
  def apply_one_of_formatters(
159
185
  formatter_condition_pairs: Sequence[
160
- Tuple[Callable[..., bool], Callable[..., TReturn]]
186
+ Tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]]
161
187
  ],
162
- value: TValue,
163
- ) -> TReturn:
164
- ...
188
+ value: TArg,
189
+ ) -> TReturn: ...
165
190
 
166
191
 
167
192
  # This is just a stub to appease mypy, it gets overwritten later
168
193
  def apply_one_of_formatters(
169
194
  formatter_condition_pairs: Sequence[
170
- Tuple[Callable[..., bool], Callable[..., TReturn]]
195
+ Tuple[Callable[[TArg], "SupportsBool"], Callable[[TArg], TReturn]]
171
196
  ],
172
- value: TValue = None,
173
- ) -> TReturn:
174
- ...
197
+ value: Optional[TArg] = None,
198
+ ) -> TReturn: ...
175
199
 
176
200
 
177
201
  @overload
178
202
  def hexstr_if_str(
179
- to_type: Callable[..., TReturn]
180
- ) -> Callable[[Union[bytes, int, str]], TReturn]:
181
- ...
203
+ to_type: Callable[..., TReturn],
204
+ ) -> Callable[[Union[bytes, int, str]], TReturn]: ...
182
205
 
183
206
 
184
207
  @overload
185
208
  def hexstr_if_str(
186
209
  to_type: Callable[..., TReturn], to_format: Union[bytes, int, str]
187
- ) -> TReturn:
188
- ...
210
+ ) -> TReturn: ...
189
211
 
190
212
 
191
213
  # This is just a stub to appease mypy, it gets overwritten later
192
- def hexstr_if_str(
193
- to_type: Callable[..., TReturn], to_format: Union[bytes, int, str] = None
194
- ) -> TReturn:
195
- ...
214
+ def hexstr_if_str( # type: ignore
215
+ to_type: Callable[..., TReturn], to_format: Optional[Union[bytes, int, str]] = None
216
+ ) -> TReturn: ...
196
217
 
197
218
 
198
219
  @overload
199
220
  def text_if_str(
200
- to_type: Callable[..., TReturn]
201
- ) -> Callable[[Union[bytes, int, str]], TReturn]:
202
- ...
221
+ to_type: Callable[..., TReturn],
222
+ ) -> Callable[[Union[bytes, int, str]], TReturn]: ...
203
223
 
204
224
 
205
225
  @overload
206
226
  def text_if_str(
207
227
  to_type: Callable[..., TReturn], text_or_primitive: Union[bytes, int, str]
208
- ) -> TReturn:
209
- ...
228
+ ) -> TReturn: ...
210
229
 
211
230
 
212
231
  # This is just a stub to appease mypy, it gets overwritten later
213
- def text_if_str(
214
- to_type: Callable[..., TReturn], text_or_primitive: Union[bytes, int, str] = None
215
- ) -> TReturn:
216
- ...
232
+ def text_if_str( # type: ignore
233
+ to_type: Callable[..., TReturn],
234
+ text_or_primitive: Optional[Union[bytes, int, str]] = None,
235
+ ) -> TReturn: ...
217
236
 
218
237
 
219
238
  @overload
220
239
  def apply_formatters_to_dict(
221
- formatters: Dict[Any, Any]
222
- ) -> Callable[[Dict[Any, Any]], TReturn]:
240
+ formatters: Dict[Any, Any], unaliased: bool = False
241
+ ) -> Callable[[Union[Dict[Any, Any], CamelModel]], Dict[Any, Any]]:
223
242
  ...
224
243
 
225
244
 
226
245
  @overload
227
246
  def apply_formatters_to_dict(
228
- formatters: Dict[Any, Any], value: Dict[Any, Any]
229
- ) -> TReturn:
247
+ formatters: Dict[Any, Any], value: Union[Dict[Any, Any], CamelModel], unaliased: bool = False
248
+ ) -> Dict[Any, Any]:
230
249
  ...
231
250
 
232
251
 
233
252
  # This is just a stub to appease mypy, it gets overwritten later
234
253
  def apply_formatters_to_dict(
235
- formatters: Dict[Any, Any], value: Optional[Dict[Any, Any]] = None
236
- ) -> TReturn:
237
- ...
254
+ formatters: Dict[Any, Any],
255
+ value: Optional[Union[Dict[Any, Any], CamelModel]] = None,
256
+ unaliased: bool = False,
257
+ ) -> Dict[Any, Any]: ...
238
258
 
239
259
 
240
260
  apply_formatter_at_index = curry(apply_formatter_at_index)
241
- apply_formatter_if = curry(non_curried_apply_formatter_if)
261
+ apply_formatter_if = curry(non_curried_apply_formatter_if) # noqa: F811
242
262
  apply_formatter_to_array = curry(apply_formatter_to_array)
243
- apply_formatters_to_dict = curry(non_curried_apply_formatters_to_dict)
263
+ apply_formatters_to_dict = curry(non_curried_apply_formatters_to_dict) # noqa: F811
244
264
  apply_formatters_to_sequence = curry(apply_formatters_to_sequence)
245
265
  apply_key_map = curry(apply_key_map)
246
- apply_one_of_formatters = curry(non_curried_apply_one_of_formatters)
266
+ apply_one_of_formatters = curry(non_curried_apply_one_of_formatters) # noqa: F811
267
+ filter_abi_by_name = curry(filter_abi_by_name)
268
+ filter_abi_by_type = curry(filter_abi_by_type)
269
+ flatten_return = curry(flatten_return)
247
270
  from_wei = curry(from_wei)
271
+ from_wei_decimals = curry(from_wei_decimals)
272
+ get_aligned_abi_inputs = curry(get_aligned_abi_inputs)
248
273
  get_logger = curry(get_logger)
249
- hexstr_if_str = curry(non_curried_hexstr_if_str)
274
+ get_normalized_abi_inputs = curry(get_normalized_abi_inputs)
275
+ hexstr_if_str = curry(non_curried_hexstr_if_str) # noqa: F811
250
276
  is_same_address = curry(is_same_address)
251
- text_if_str = curry(non_curried_text_if_str)
277
+ sort_return = curry(sort_return)
278
+ text_if_str = curry(non_curried_text_if_str) # noqa: F811
279
+ to_ordered_dict = curry(to_ordered_dict)
252
280
  to_wei = curry(to_wei)
281
+ to_wei_decimals = curry(to_wei_decimals)
253
282
  clamp = curry(clamp)
254
283
 
255
284
  # Delete any methods and classes that are not intended to be importable from
256
- # eth_utils.curried
257
- # We do this approach instead of __all__ because this approach actually prevents
258
- # importing the wrong thing, while __all__ only affects `from eth_utils.curried import *`
285
+ # `eth_utils.curried`. We do this approach instead of __all__ because this approach
286
+ # actually prevents importing the wrong thing, while __all__ only affects
287
+ # `from eth_utils.curried import *`
259
288
  del Any
260
289
  del Callable
261
290
  del Dict
@@ -265,6 +294,7 @@ del Sequence
265
294
  del TReturn
266
295
  del TValue
267
296
  del Tuple
297
+ del TypeGuard
268
298
  del TypeVar
269
299
  del Union
270
300
  del curry
Binary file
faster_eth_utils/debug.py CHANGED
@@ -5,15 +5,15 @@ import sys
5
5
 
6
6
  def pip_freeze() -> str:
7
7
  result = subprocess.run("python -m pip freeze".split(), stdout=subprocess.PIPE)
8
- return "python -m pip freeze result:\n%s" % result.stdout.decode()
8
+ return f"python -m pip freeze result:\n{result.stdout.decode()}"
9
9
 
10
10
 
11
11
  def python_version() -> str:
12
- return "Python version:\n%s" % sys.version
12
+ return f"Python version:\n{sys.version}"
13
13
 
14
14
 
15
15
  def platform_info() -> str:
16
- return "Operating System: %s" % platform.platform()
16
+ return f"Operating System: {platform.platform()}"
17
17
 
18
18
 
19
19
  def get_environment_summary() -> str:
Binary file
@@ -1,56 +1,107 @@
1
1
  import functools
2
- import itertools
3
- from typing import Any, Callable, Dict, Type, TypeVar, final
4
-
5
- from .types import is_text
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")
6
19
 
7
20
  T = TypeVar("T")
8
21
 
22
+ TInstance = TypeVar("TInstance", bound=object)
23
+ """A TypeVar representing an instance that a method can bind to."""
24
+
9
25
 
10
26
  @final
11
- class combomethod(object):
12
- def __init__(self, method: Callable[..., Any]) -> None:
13
- self.method = method
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]:
14
41
 
15
- def __get__(self, obj: T = None, objtype: Type[T] = None) -> Callable[..., Any]:
16
42
  @functools.wraps(self.method)
17
- def _wrapper(*args: Any, **kwargs: Any) -> Any:
43
+ def _wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
18
44
  if obj is not None:
19
45
  return self.method(obj, *args, **kwargs)
20
46
  else:
21
- return self.method(objtype, *args, **kwargs)
47
+ return self.method(objtype, *args, **kwargs) # type: ignore [arg-type]
22
48
 
23
49
  return _wrapper
24
50
 
25
51
 
26
- def return_arg_type(at_position: int) -> Callable[..., Callable[..., T]]:
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]]:
27
59
  """
28
60
  Wrap the return value with the result of `type(args[at_position])`.
29
61
  """
62
+ if deco := _return_arg_type_deco_cache.get(at_position):
63
+ return deco
30
64
 
31
- def decorator(to_wrap: Callable[..., Any]) -> Callable[..., T]:
65
+ def decorator(to_wrap: Callable[P, Any]) -> Callable[P, Any]:
32
66
  @functools.wraps(to_wrap)
33
- def wrapper(*args: Any, **kwargs: Any) -> T:
67
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> Any:
34
68
  result = to_wrap(*args, **kwargs)
35
69
  ReturnType = type(args[at_position])
36
- return ReturnType(result) # type: ignore
70
+ return ReturnType(result) # type: ignore [call-arg]
37
71
 
38
72
  return wrapper
39
73
 
74
+ _return_arg_type_deco_cache[at_position] = decorator
75
+
40
76
  return decorator
41
77
 
42
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
+
43
90
  def replace_exceptions(
44
- old_to_new_exceptions: Dict[Type[BaseException], Type[BaseException]]
45
- ) -> Callable[[Callable[..., T]], Callable[..., T]]:
91
+ old_to_new_exceptions: Dict[ExcType, ExcType],
92
+ ) -> Callable[[Callable[P, T]], Callable[P, T]]:
46
93
  """
47
94
  Replaces old exceptions with new exceptions to be raised in their place.
48
95
  """
49
- old_exceptions = tuple(old_to_new_exceptions.keys())
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)
50
101
 
51
- def decorator(to_wrap: Callable[..., T]) -> Callable[..., T]:
102
+ def decorator(to_wrap: Callable[P, T]) -> Callable[P, T]:
52
103
  @functools.wraps(to_wrap)
53
- def wrapped(*args: Any, **kwargs: Any) -> T:
104
+ def wrapped(*args: P.args, **kwargs: P.kwargs) -> T:
54
105
  try:
55
106
  return to_wrap(*args, **kwargs)
56
107
  except old_exceptions as err:
@@ -58,9 +109,11 @@ def replace_exceptions(
58
109
  raise old_to_new_exceptions[type(err)](err) from err
59
110
  except KeyError:
60
111
  raise TypeError(
61
- "could not look up new exception to use for %r" % err
112
+ f"could not look up new exception to use for {repr(err)}"
62
113
  ) from err
63
114
 
64
115
  return wrapped
65
116
 
117
+ _replace_exceptions_deco_cache[cache_key] = decorator
118
+
66
119
  return decorator
Binary file
Binary file
@@ -1,6 +1,11 @@
1
- class ValidationError(Exception):
1
+ """
2
+ faster-eth-utils exceptions always inherit from eth-utils exceptions, so porting to faster-eth-utils
3
+ does not require any change to your existing exception handlers. They will continue to work.
4
+ """
5
+
6
+ import eth_utils.exceptions
7
+
8
+ class ValidationError(eth_utils.exceptions.ValidationError):
2
9
  """
3
10
  Raised when something does not pass a validation check.
4
11
  """
5
-
6
- pass