web3 7.6.1__py3-none-any.whl → 7.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. ens/async_ens.py +1 -1
  2. ens/ens.py +1 -1
  3. web3/_utils/caching/caching_utils.py +64 -0
  4. web3/_utils/caching/request_caching_validation.py +1 -0
  5. web3/_utils/events.py +1 -1
  6. web3/_utils/http_session_manager.py +32 -3
  7. web3/_utils/module_testing/eth_module.py +5 -18
  8. web3/_utils/module_testing/module_testing_utils.py +1 -43
  9. web3/_utils/module_testing/persistent_connection_provider.py +696 -207
  10. web3/_utils/module_testing/utils.py +99 -33
  11. web3/beacon/api_endpoints.py +10 -0
  12. web3/beacon/async_beacon.py +47 -0
  13. web3/beacon/beacon.py +45 -0
  14. web3/contract/async_contract.py +2 -206
  15. web3/contract/base_contract.py +217 -13
  16. web3/contract/contract.py +2 -205
  17. web3/datastructures.py +15 -16
  18. web3/eth/async_eth.py +23 -5
  19. web3/exceptions.py +7 -0
  20. web3/main.py +24 -3
  21. web3/manager.py +140 -48
  22. web3/method.py +1 -1
  23. web3/middleware/attrdict.py +12 -22
  24. web3/middleware/base.py +14 -6
  25. web3/module.py +17 -21
  26. web3/providers/async_base.py +23 -14
  27. web3/providers/base.py +6 -8
  28. web3/providers/ipc.py +7 -6
  29. web3/providers/legacy_websocket.py +1 -1
  30. web3/providers/persistent/async_ipc.py +5 -3
  31. web3/providers/persistent/persistent.py +121 -17
  32. web3/providers/persistent/persistent_connection.py +11 -4
  33. web3/providers/persistent/request_processor.py +49 -41
  34. web3/providers/persistent/subscription_container.py +56 -0
  35. web3/providers/persistent/subscription_manager.py +298 -0
  36. web3/providers/persistent/websocket.py +4 -4
  37. web3/providers/rpc/async_rpc.py +16 -3
  38. web3/providers/rpc/rpc.py +9 -5
  39. web3/types.py +28 -14
  40. web3/utils/__init__.py +4 -0
  41. web3/utils/subscriptions.py +289 -0
  42. {web3-7.6.1.dist-info → web3-7.8.0.dist-info}/LICENSE +1 -1
  43. {web3-7.6.1.dist-info → web3-7.8.0.dist-info}/METADATA +68 -56
  44. {web3-7.6.1.dist-info → web3-7.8.0.dist-info}/RECORD +46 -43
  45. {web3-7.6.1.dist-info → web3-7.8.0.dist-info}/WHEEL +1 -1
  46. {web3-7.6.1.dist-info → web3-7.8.0.dist-info}/top_level.txt +0 -0
web3/types.py CHANGED
@@ -36,13 +36,9 @@ from web3._utils.compat import (
36
36
  )
37
37
 
38
38
  if TYPE_CHECKING:
39
- from web3.contract.async_contract import ( # noqa: F401
40
- AsyncContractEvent,
41
- AsyncContractFunction,
42
- )
43
- from web3.contract.contract import ( # noqa: F401
44
- ContractEvent,
45
- ContractFunction,
39
+ from web3.contract.base_contract import (
40
+ BaseContractEvent,
41
+ BaseContractFunction,
46
42
  )
47
43
  from web3.main import ( # noqa: F401
48
44
  AsyncWeb3,
@@ -262,6 +258,13 @@ EthSubscriptionParams = Union[
262
258
  RPCId = Optional[Union[int, str]]
263
259
 
264
260
 
261
+ class RPCRequest(TypedDict, total=False):
262
+ id: RPCId
263
+ jsonrpc: Literal["2.0"]
264
+ method: RPCEndpoint
265
+ params: Any
266
+
267
+
265
268
  class RPCResponse(TypedDict, total=False):
266
269
  error: RPCError
267
270
  id: RPCId
@@ -273,11 +276,19 @@ class RPCResponse(TypedDict, total=False):
273
276
  params: EthSubscriptionParams
274
277
 
275
278
 
279
+ EthSubscriptionResult = Union[
280
+ BlockData, # newHeads
281
+ TxData, # newPendingTransactions, full_transactions=True
282
+ HexBytes, # newPendingTransactions, full_transactions=False
283
+ LogReceipt, # logs
284
+ SyncProgress, # syncing
285
+ GethSyncingSubscriptionResult, # geth syncing
286
+ ]
287
+
288
+
276
289
  class FormattedEthSubscriptionResponse(TypedDict):
277
290
  subscription: HexStr
278
- result: Union[
279
- BlockData, TxData, LogReceipt, SyncProgress, GethSyncingSubscriptionResult
280
- ]
291
+ result: EthSubscriptionResult
281
292
 
282
293
 
283
294
  class CreateAccessListResponse(TypedDict):
@@ -286,10 +297,13 @@ class CreateAccessListResponse(TypedDict):
286
297
 
287
298
 
288
299
  MakeRequestFn = Callable[[RPCEndpoint, Any], RPCResponse]
289
- MakeBatchRequestFn = Callable[[List[Tuple[RPCEndpoint, Any]]], List[RPCResponse]]
300
+ MakeBatchRequestFn = Callable[
301
+ [List[Tuple[RPCEndpoint, Any]]], Union[List[RPCResponse], RPCResponse]
302
+ ]
290
303
  AsyncMakeRequestFn = Callable[[RPCEndpoint, Any], Coroutine[Any, Any, RPCResponse]]
291
304
  AsyncMakeBatchRequestFn = Callable[
292
- [List[Tuple[RPCEndpoint, Any]]], Coroutine[Any, Any, List[RPCResponse]]
305
+ [List[Tuple[RPCEndpoint, Any]]],
306
+ Coroutine[Any, Any, Union[List[RPCResponse], RPCResponse]],
293
307
  ]
294
308
 
295
309
 
@@ -566,8 +580,8 @@ class GethWallet(TypedDict):
566
580
 
567
581
  # Contract types
568
582
 
569
- TContractFn = TypeVar("TContractFn", "ContractFunction", "AsyncContractFunction")
570
- TContractEvent = TypeVar("TContractEvent", "ContractEvent", "AsyncContractEvent")
583
+ TContractFn = TypeVar("TContractFn", bound="BaseContractFunction")
584
+ TContractEvent = TypeVar("TContractEvent", bound="BaseContractEvent")
571
585
 
572
586
 
573
587
  # Tracing types
web3/utils/__init__.py CHANGED
@@ -42,6 +42,9 @@ from .caching import (
42
42
  from .exception_handling import (
43
43
  handle_offchain_lookup,
44
44
  )
45
+ from .subscriptions import (
46
+ EthSubscription,
47
+ )
45
48
 
46
49
  __all__ = [
47
50
  "abi_to_signature",
@@ -70,5 +73,6 @@ __all__ = [
70
73
  "async_handle_offchain_lookup",
71
74
  "RequestCacheValidationThreshold",
72
75
  "SimpleCache",
76
+ "EthSubscription",
73
77
  "handle_offchain_lookup",
74
78
  ]
@@ -0,0 +1,289 @@
1
+ from typing import (
2
+ TYPE_CHECKING,
3
+ Any,
4
+ Callable,
5
+ Coroutine,
6
+ Dict,
7
+ Generic,
8
+ List,
9
+ Optional,
10
+ Sequence,
11
+ TypeVar,
12
+ Union,
13
+ )
14
+
15
+ from eth_typing import (
16
+ Address,
17
+ ChecksumAddress,
18
+ HexStr,
19
+ )
20
+ from hexbytes import (
21
+ HexBytes,
22
+ )
23
+
24
+ from web3.exceptions import (
25
+ Web3AttributeError,
26
+ Web3ValueError,
27
+ )
28
+ from web3.types import (
29
+ BlockData,
30
+ FilterParams,
31
+ LogReceipt,
32
+ SyncProgress,
33
+ TxData,
34
+ )
35
+
36
+ if TYPE_CHECKING:
37
+ from web3 import (
38
+ AsyncWeb3,
39
+ )
40
+ from web3.providers.persistent.subscription_manager import (
41
+ SubscriptionManager,
42
+ )
43
+ from web3.types import EthSubscriptionResult # noqa: F401
44
+
45
+
46
+ TSubscriptionResult = TypeVar("TSubscriptionResult", bound="EthSubscriptionResult")
47
+ TSubscription = TypeVar("TSubscription", bound="EthSubscription[Any]")
48
+
49
+
50
+ class EthSubscriptionContext(Generic[TSubscription, TSubscriptionResult]):
51
+ def __init__(
52
+ self,
53
+ async_w3: "AsyncWeb3",
54
+ subscription: TSubscription,
55
+ result: TSubscriptionResult,
56
+ **kwargs: Any,
57
+ ) -> None:
58
+ self.async_w3 = async_w3
59
+ self.subscription = subscription
60
+ self.result = result
61
+ self.__dict__.update(kwargs)
62
+
63
+ def __getattr__(self, item: str) -> Any:
64
+ if item in self.__dict__:
65
+ return self.__dict__[item]
66
+ raise Web3AttributeError(
67
+ f"'{self.__class__.__name__}' object has no attribute '{item}'"
68
+ )
69
+
70
+
71
+ EthSubscriptionHandler = Callable[
72
+ [EthSubscriptionContext[Any, Any]], Coroutine[Any, Any, None]
73
+ ]
74
+
75
+
76
+ def handler_wrapper(
77
+ handler: Optional[EthSubscriptionHandler],
78
+ ) -> Optional[EthSubscriptionHandler]:
79
+ """Wrap the handler to add bookkeeping and context creation."""
80
+ if handler is None:
81
+ return None
82
+
83
+ async def wrapped_handler(
84
+ context: EthSubscriptionContext[TSubscription, TSubscriptionResult],
85
+ ) -> None:
86
+ sub = context.subscription
87
+ sub.handler_call_count += 1
88
+ sub.manager.total_handler_calls += 1
89
+ sub.manager.logger.debug(
90
+ f"Subscription handler called.\n"
91
+ f" label: {sub.label}\n"
92
+ f" call count: {sub.handler_call_count}\n"
93
+ f" total handler calls: {sub.manager.total_handler_calls}"
94
+ )
95
+ await handler(context)
96
+
97
+ return wrapped_handler
98
+
99
+
100
+ class EthSubscription(Generic[TSubscriptionResult]):
101
+ _id: HexStr = None
102
+ manager: "SubscriptionManager" = None
103
+
104
+ def __init__(
105
+ self: TSubscription,
106
+ subscription_params: Optional[Sequence[Any]] = None,
107
+ handler: Optional[EthSubscriptionHandler] = None,
108
+ handler_context: Optional[Dict[str, Any]] = None,
109
+ label: Optional[str] = None,
110
+ ) -> None:
111
+ self._subscription_params = subscription_params
112
+ self._handler = handler_wrapper(handler)
113
+ self._handler_context = handler_context or {}
114
+ self._label = label
115
+ self.handler_call_count = 0
116
+
117
+ @property
118
+ def _default_label(self) -> str:
119
+ return f"{self.__class__.__name__}{self.subscription_params}"
120
+
121
+ @classmethod
122
+ def _create_type_aware_subscription(
123
+ cls,
124
+ subscription_params: Optional[Sequence[Any]],
125
+ handler: Optional[EthSubscriptionHandler] = None,
126
+ handler_context: Optional[Dict[str, Any]] = None,
127
+ label: Optional[str] = None,
128
+ ) -> "EthSubscription[Any]":
129
+ subscription_type = subscription_params[0]
130
+ subscription_arg = (
131
+ subscription_params[1] if len(subscription_params) > 1 else None
132
+ )
133
+ if subscription_type == "newHeads":
134
+ return NewHeadsSubscription(
135
+ handler=handler, handler_context=handler_context, label=label
136
+ )
137
+ elif subscription_type == "logs":
138
+ subscription_arg = subscription_arg or {}
139
+ return LogsSubscription(
140
+ **subscription_arg,
141
+ handler=handler,
142
+ handler_context=handler_context,
143
+ label=label,
144
+ )
145
+ elif subscription_type == "newPendingTransactions":
146
+ subscription_arg = subscription_arg or False
147
+ return PendingTxSubscription(
148
+ full_transactions=subscription_arg,
149
+ handler=handler,
150
+ handler_context=handler_context,
151
+ label=label,
152
+ )
153
+ elif subscription_type == "syncing":
154
+ return SyncingSubscription(
155
+ handler=handler, handler_context=handler_context, label=label
156
+ )
157
+ else:
158
+ params = (
159
+ (subscription_type, subscription_arg)
160
+ if subscription_arg
161
+ else (subscription_type,)
162
+ )
163
+ return cls(
164
+ params,
165
+ handler=handler,
166
+ handler_context=handler_context,
167
+ label=label,
168
+ )
169
+
170
+ @property
171
+ def subscription_params(self) -> Sequence[Any]:
172
+ return self._subscription_params
173
+
174
+ @property
175
+ def label(self) -> str:
176
+ if not self._label:
177
+ self._label = self._default_label
178
+ return self._label
179
+
180
+ @property
181
+ def id(self) -> HexStr:
182
+ if not self._id:
183
+ raise Web3ValueError("No `id` found for subscription.")
184
+ return self._id
185
+
186
+ async def unsubscribe(self) -> bool:
187
+ return await self.manager.unsubscribe(self)
188
+
189
+
190
+ LogsSubscriptionContext = EthSubscriptionContext[
191
+ "LogsSubscription", "EthSubscriptionResult"
192
+ ]
193
+ LogsSubscriptionHandler = Callable[[LogsSubscriptionContext], Coroutine[Any, Any, None]]
194
+
195
+
196
+ class LogsSubscription(EthSubscription[LogReceipt]):
197
+ def __init__(
198
+ self,
199
+ address: Optional[
200
+ Union[Address, ChecksumAddress, List[Address], List[ChecksumAddress]]
201
+ ] = None,
202
+ topics: Optional[List[HexStr]] = None,
203
+ handler: LogsSubscriptionHandler = None,
204
+ handler_context: Optional[Dict[str, Any]] = None,
205
+ label: Optional[str] = None,
206
+ ) -> None:
207
+ self.address = address
208
+ self.topics = topics
209
+
210
+ logs_filter: FilterParams = {}
211
+ if address:
212
+ logs_filter["address"] = address
213
+ if topics:
214
+ logs_filter["topics"] = topics
215
+ self.logs_filter = logs_filter
216
+
217
+ super().__init__(
218
+ subscription_params=("logs", logs_filter),
219
+ handler=handler,
220
+ handler_context=handler_context,
221
+ label=label,
222
+ )
223
+
224
+
225
+ NewHeadsSubscriptionContext = EthSubscriptionContext["NewHeadsSubscription", BlockData]
226
+ NewHeadsSubscriptionHandler = Callable[
227
+ [NewHeadsSubscriptionContext], Coroutine[Any, Any, None]
228
+ ]
229
+
230
+
231
+ class NewHeadsSubscription(EthSubscription[BlockData]):
232
+ def __init__(
233
+ self,
234
+ label: Optional[str] = None,
235
+ handler: Optional[NewHeadsSubscriptionHandler] = None,
236
+ handler_context: Optional[Dict[str, Any]] = None,
237
+ ) -> None:
238
+ super().__init__(
239
+ subscription_params=("newHeads",),
240
+ handler=handler,
241
+ handler_context=handler_context,
242
+ label=label,
243
+ )
244
+
245
+
246
+ PendingTxSubscriptionContext = EthSubscriptionContext[
247
+ "PendingTxSubscription", Union[HexBytes, TxData]
248
+ ]
249
+ PendingTxSubscriptionHandler = Callable[
250
+ [PendingTxSubscriptionContext], Coroutine[Any, Any, None]
251
+ ]
252
+
253
+
254
+ class PendingTxSubscription(EthSubscription[Union[HexBytes, TxData]]):
255
+ def __init__(
256
+ self,
257
+ full_transactions: bool = False,
258
+ label: Optional[str] = None,
259
+ handler: Optional[PendingTxSubscriptionHandler] = None,
260
+ handler_context: Optional[Dict[str, Any]] = None,
261
+ ) -> None:
262
+ self.full_transactions = full_transactions
263
+ super().__init__(
264
+ subscription_params=("newPendingTransactions", full_transactions),
265
+ handler=handler,
266
+ handler_context=handler_context,
267
+ label=label,
268
+ )
269
+
270
+
271
+ SyncingSubscriptionContext = EthSubscriptionContext["SyncingSubscription", SyncProgress]
272
+ SyncingSubscriptionHandler = Callable[
273
+ [SyncingSubscriptionContext], Coroutine[Any, Any, None]
274
+ ]
275
+
276
+
277
+ class SyncingSubscription(EthSubscription[SyncProgress]):
278
+ def __init__(
279
+ self,
280
+ label: Optional[str] = None,
281
+ handler: Optional[SyncingSubscriptionHandler] = None,
282
+ handler_context: Optional[Dict[str, Any]] = None,
283
+ ) -> None:
284
+ super().__init__(
285
+ subscription_params=("syncing",),
286
+ handler=handler,
287
+ handler_context=handler_context,
288
+ label=label,
289
+ )
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2016-2024 The Ethereum Foundation
3
+ Copyright (c) 2016-2025 The Ethereum Foundation
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: web3
3
- Version: 7.6.1
3
+ Version: 7.8.0
4
4
  Summary: web3: A Python library for interacting with Ethereum
5
5
  Home-page: https://github.com/ethereum/web3.py
6
6
  Author: The Ethereum Foundation
@@ -21,63 +21,75 @@ Classifier: Programming Language :: Python :: 3.13
21
21
  Requires-Python: >=3.8, <4
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
- Requires-Dist: eth-abi >=5.0.1
25
- Requires-Dist: eth-account >=0.13.1
26
- Requires-Dist: eth-hash[pycryptodome] >=0.5.1
27
- Requires-Dist: eth-typing >=5.0.0
28
- Requires-Dist: eth-utils >=5.0.0
29
- Requires-Dist: hexbytes >=1.2.0
30
- Requires-Dist: aiohttp >=3.7.4.post0
31
- Requires-Dist: pydantic >=2.4.0
32
- Requires-Dist: requests >=2.23.0
33
- Requires-Dist: typing-extensions >=4.0.1
34
- Requires-Dist: types-requests >=2.0.0
35
- Requires-Dist: websockets <14.0.0,>=10.0.0
36
- Requires-Dist: pyunormalize >=15.0.0
37
- Requires-Dist: pywin32 >=223 ; platform_system == "Windows"
24
+ Requires-Dist: eth-abi>=5.0.1
25
+ Requires-Dist: eth-account>=0.13.1
26
+ Requires-Dist: eth-hash[pycryptodome]>=0.5.1
27
+ Requires-Dist: eth-typing>=5.0.0
28
+ Requires-Dist: eth-utils>=5.0.0
29
+ Requires-Dist: hexbytes>=1.2.0
30
+ Requires-Dist: aiohttp>=3.7.4.post0
31
+ Requires-Dist: pydantic>=2.4.0
32
+ Requires-Dist: pywin32>=223; platform_system == "Windows"
33
+ Requires-Dist: requests>=2.23.0
34
+ Requires-Dist: typing-extensions>=4.0.1
35
+ Requires-Dist: types-requests>=2.0.0
36
+ Requires-Dist: websockets<14.0.0,>=10.0.0
37
+ Requires-Dist: pyunormalize>=15.0.0
38
+ Provides-Extra: tester
39
+ Requires-Dist: eth-tester[py-evm]<0.13.0b1,>=0.12.0b1; extra == "tester"
40
+ Requires-Dist: py-geth>=5.1.0; extra == "tester"
38
41
  Provides-Extra: dev
39
- Requires-Dist: build >=0.9.0 ; extra == 'dev'
40
- Requires-Dist: bumpversion >=0.5.3 ; extra == 'dev'
41
- Requires-Dist: ipython ; extra == 'dev'
42
- Requires-Dist: setuptools >=38.6.0 ; extra == 'dev'
43
- Requires-Dist: tqdm >4.32 ; extra == 'dev'
44
- Requires-Dist: twine >=1.13 ; extra == 'dev'
45
- Requires-Dist: wheel ; extra == 'dev'
46
- Requires-Dist: sphinx >=6.0.0 ; extra == 'dev'
47
- Requires-Dist: sphinx-autobuild >=2021.3.14 ; extra == 'dev'
48
- Requires-Dist: sphinx-rtd-theme >=1.0.0 ; extra == 'dev'
49
- Requires-Dist: towncrier <22,>=21 ; extra == 'dev'
50
- Requires-Dist: pytest-asyncio <0.23,>=0.18.1 ; extra == 'dev'
51
- Requires-Dist: pytest-mock >=1.10 ; extra == 'dev'
52
- Requires-Dist: pytest-xdist >=2.4.0 ; extra == 'dev'
53
- Requires-Dist: pytest >=7.0.0 ; extra == 'dev'
54
- Requires-Dist: flaky >=3.7.0 ; extra == 'dev'
55
- Requires-Dist: hypothesis >=3.31.2 ; extra == 'dev'
56
- Requires-Dist: tox >=4.0.0 ; extra == 'dev'
57
- Requires-Dist: mypy ==1.10.0 ; extra == 'dev'
58
- Requires-Dist: pre-commit >=3.4.0 ; extra == 'dev'
59
- Requires-Dist: eth-tester[py-evm] <0.13.0b1,>=0.12.0b1 ; extra == 'dev'
60
- Requires-Dist: py-geth >=5.1.0 ; extra == 'dev'
42
+ Requires-Dist: build>=0.9.0; extra == "dev"
43
+ Requires-Dist: bumpversion>=0.5.3; extra == "dev"
44
+ Requires-Dist: ipython; extra == "dev"
45
+ Requires-Dist: setuptools>=38.6.0; extra == "dev"
46
+ Requires-Dist: tqdm>4.32; extra == "dev"
47
+ Requires-Dist: twine>=1.13; extra == "dev"
48
+ Requires-Dist: wheel; extra == "dev"
49
+ Requires-Dist: sphinx>=6.0.0; extra == "dev"
50
+ Requires-Dist: sphinx-autobuild>=2021.3.14; extra == "dev"
51
+ Requires-Dist: sphinx_rtd_theme>=1.0.0; extra == "dev"
52
+ Requires-Dist: towncrier<22,>=21; extra == "dev"
53
+ Requires-Dist: pytest-asyncio<0.23,>=0.18.1; extra == "dev"
54
+ Requires-Dist: pytest-mock>=1.10; extra == "dev"
55
+ Requires-Dist: pytest-xdist>=2.4.0; extra == "dev"
56
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
57
+ Requires-Dist: flaky>=3.7.0; extra == "dev"
58
+ Requires-Dist: hypothesis>=3.31.2; extra == "dev"
59
+ Requires-Dist: tox>=4.0.0; extra == "dev"
60
+ Requires-Dist: mypy==1.10.0; extra == "dev"
61
+ Requires-Dist: pre-commit>=3.4.0; extra == "dev"
62
+ Requires-Dist: eth-tester[py-evm]<0.13.0b1,>=0.12.0b1; extra == "dev"
63
+ Requires-Dist: py-geth>=5.1.0; extra == "dev"
61
64
  Provides-Extra: docs
62
- Requires-Dist: sphinx >=6.0.0 ; extra == 'docs'
63
- Requires-Dist: sphinx-autobuild >=2021.3.14 ; extra == 'docs'
64
- Requires-Dist: sphinx-rtd-theme >=1.0.0 ; extra == 'docs'
65
- Requires-Dist: towncrier <22,>=21 ; extra == 'docs'
65
+ Requires-Dist: sphinx>=6.0.0; extra == "docs"
66
+ Requires-Dist: sphinx-autobuild>=2021.3.14; extra == "docs"
67
+ Requires-Dist: sphinx_rtd_theme>=1.0.0; extra == "docs"
68
+ Requires-Dist: towncrier<22,>=21; extra == "docs"
66
69
  Provides-Extra: test
67
- Requires-Dist: pytest-asyncio <0.23,>=0.18.1 ; extra == 'test'
68
- Requires-Dist: pytest-mock >=1.10 ; extra == 'test'
69
- Requires-Dist: pytest-xdist >=2.4.0 ; extra == 'test'
70
- Requires-Dist: pytest >=7.0.0 ; extra == 'test'
71
- Requires-Dist: flaky >=3.7.0 ; extra == 'test'
72
- Requires-Dist: hypothesis >=3.31.2 ; extra == 'test'
73
- Requires-Dist: tox >=4.0.0 ; extra == 'test'
74
- Requires-Dist: mypy ==1.10.0 ; extra == 'test'
75
- Requires-Dist: pre-commit >=3.4.0 ; extra == 'test'
76
- Requires-Dist: eth-tester[py-evm] <0.13.0b1,>=0.12.0b1 ; extra == 'test'
77
- Requires-Dist: py-geth >=5.1.0 ; extra == 'test'
78
- Provides-Extra: tester
79
- Requires-Dist: eth-tester[py-evm] <0.13.0b1,>=0.12.0b1 ; extra == 'tester'
80
- Requires-Dist: py-geth >=5.1.0 ; extra == 'tester'
70
+ Requires-Dist: pytest-asyncio<0.23,>=0.18.1; extra == "test"
71
+ Requires-Dist: pytest-mock>=1.10; extra == "test"
72
+ Requires-Dist: pytest-xdist>=2.4.0; extra == "test"
73
+ Requires-Dist: pytest>=7.0.0; extra == "test"
74
+ Requires-Dist: flaky>=3.7.0; extra == "test"
75
+ Requires-Dist: hypothesis>=3.31.2; extra == "test"
76
+ Requires-Dist: tox>=4.0.0; extra == "test"
77
+ Requires-Dist: mypy==1.10.0; extra == "test"
78
+ Requires-Dist: pre-commit>=3.4.0; extra == "test"
79
+ Requires-Dist: eth-tester[py-evm]<0.13.0b1,>=0.12.0b1; extra == "test"
80
+ Requires-Dist: py-geth>=5.1.0; extra == "test"
81
+ Dynamic: author
82
+ Dynamic: author-email
83
+ Dynamic: classifier
84
+ Dynamic: description
85
+ Dynamic: description-content-type
86
+ Dynamic: home-page
87
+ Dynamic: keywords
88
+ Dynamic: license
89
+ Dynamic: provides-extra
90
+ Dynamic: requires-dist
91
+ Dynamic: requires-python
92
+ Dynamic: summary
81
93
 
82
94
  # web3.py
83
95