web3 7.12.0__py3-none-any.whl → 7.13.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.
@@ -724,8 +724,6 @@ class AsyncEthModuleTest:
724
724
  keyfile_account_pkey: HexStr,
725
725
  async_math_contract: "AsyncContract",
726
726
  ) -> None:
727
- # TODO: remove blockNumber block_id from eth_call and eth_getCode calls once
728
- # geth behavior for "latest" seems stable again.
729
727
  keyfile_account = async_w3.eth.account.from_key(keyfile_account_pkey)
730
728
 
731
729
  chain_id = await async_w3.eth.chain_id
@@ -757,13 +755,9 @@ class AsyncEthModuleTest:
757
755
  signed = keyfile_account.sign_transaction(txn)
758
756
  tx_hash = await async_w3.eth.send_raw_transaction(signed.raw_transaction)
759
757
  get_tx = await async_w3.eth.get_transaction(tx_hash)
760
- tx_receipt = await async_w3.eth.wait_for_transaction_receipt(
761
- tx_hash, timeout=10
762
- )
758
+ await async_w3.eth.wait_for_transaction_receipt(tx_hash)
763
759
 
764
- code = await async_w3.eth.get_code(
765
- keyfile_account.address, block_identifier=tx_receipt["blockNumber"]
766
- )
760
+ code = await async_w3.eth.get_code(keyfile_account.address)
767
761
  assert code.to_0x_hex() == f"0xef0100{async_math_contract.address[2:].lower()}"
768
762
  delegated = async_w3.eth.contract(
769
763
  address=keyfile_account.address, abi=async_math_contract.abi
@@ -772,7 +766,7 @@ class AsyncEthModuleTest:
772
766
  # assert the math counter is increased by 1337 only in delegated acct
773
767
  assert await async_math_contract.functions.counter().call() == math_counter
774
768
  delegated_call = await delegated.functions.counter().call(
775
- block_identifier=tx_receipt["blockNumber"]
769
+ block_identifier="latest"
776
770
  )
777
771
  assert delegated_call == math_counter + 1337
778
772
 
@@ -803,13 +797,9 @@ class AsyncEthModuleTest:
803
797
 
804
798
  # test eth_sendTransaction
805
799
  reset_tx_hash = await async_w3.eth.send_transaction(reset_code_txn)
806
- reset_tx_receipt = await async_w3.eth.wait_for_transaction_receipt(
807
- reset_tx_hash, timeout=10
808
- )
800
+ await async_w3.eth.wait_for_transaction_receipt(reset_tx_hash, timeout=10)
809
801
 
810
- reset_code = await async_w3.eth.get_code(
811
- keyfile_account.address, reset_tx_receipt["blockNumber"]
812
- )
802
+ reset_code = await async_w3.eth.get_code(keyfile_account.address)
813
803
  assert reset_code == HexBytes("0x")
814
804
 
815
805
  @pytest.mark.asyncio
@@ -3875,8 +3865,6 @@ class EthModuleTest:
3875
3865
  def test_sign_authorization_send_raw_and_send_set_code_transactions(
3876
3866
  self, w3: "Web3", keyfile_account_pkey: HexStr, math_contract: "Contract"
3877
3867
  ) -> None:
3878
- # TODO: remove blockNumber block_id from eth_call and eth_getCode calls once
3879
- # geth behavior for "latest" seems stable again.
3880
3868
  keyfile_account = w3.eth.account.from_key(keyfile_account_pkey)
3881
3869
 
3882
3870
  chain_id = w3.eth.chain_id
@@ -3906,28 +3894,18 @@ class EthModuleTest:
3906
3894
 
3907
3895
  # test eth_sendRawTransaction
3908
3896
  signed = keyfile_account.sign_transaction(txn)
3909
- tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
3910
- get_tx = w3.eth.get_transaction(tx_hash)
3911
- receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=10)
3897
+ w3.eth.send_raw_transaction(signed.raw_transaction)
3898
+ get_tx = w3.eth.get_transaction(signed.hash)
3899
+ w3.eth.wait_for_transaction_receipt(signed.hash)
3912
3900
 
3913
- code = w3.eth.get_code(
3914
- keyfile_account.address, block_identifier=receipt["blockNumber"]
3915
- )
3901
+ code = w3.eth.get_code(keyfile_account.address)
3916
3902
  assert code.to_0x_hex() == f"0xef0100{math_contract.address[2:].lower()}"
3917
3903
  delegated = w3.eth.contract(
3918
3904
  address=keyfile_account.address, abi=math_contract.abi
3919
3905
  )
3920
3906
  # assert the math counter is increased by 1337 only in delegated acct
3921
- assert (
3922
- math_contract.functions.counter().call(
3923
- block_identifier=receipt["blockNumber"]
3924
- )
3925
- == math_counter
3926
- )
3927
- assert (
3928
- delegated.functions.counter().call(block_identifier=receipt["blockNumber"])
3929
- == math_counter + 1337
3930
- )
3907
+ assert math_contract.functions.counter().call() == math_counter
3908
+ assert delegated.functions.counter().call() == math_counter + 1337
3931
3909
 
3932
3910
  assert len(get_tx["authorizationList"]) == 1
3933
3911
  get_auth = get_tx["authorizationList"][0]
@@ -3938,7 +3916,7 @@ class EthModuleTest:
3938
3916
  assert isinstance(get_auth["r"], HexBytes)
3939
3917
  assert isinstance(get_auth["s"], HexBytes)
3940
3918
 
3941
- # reset storage value and code
3919
+ # reset code
3942
3920
  reset_auth = {
3943
3921
  "chainId": chain_id,
3944
3922
  "address": "0x" + ("00" * 20),
@@ -3956,13 +3934,9 @@ class EthModuleTest:
3956
3934
 
3957
3935
  # test eth_sendTransaction
3958
3936
  reset_tx_hash = w3.eth.send_transaction(reset_code_txn)
3959
- reset_tx_receipt = w3.eth.wait_for_transaction_receipt(
3960
- reset_tx_hash, timeout=10
3961
- )
3937
+ w3.eth.wait_for_transaction_receipt(reset_tx_hash)
3962
3938
 
3963
- reset_code = w3.eth.get_code(
3964
- keyfile_account.address, block_identifier=reset_tx_receipt["blockNumber"]
3965
- )
3939
+ reset_code = w3.eth.get_code(keyfile_account.address)
3966
3940
  assert reset_code == HexBytes("0x")
3967
3941
 
3968
3942
  def test_eth_call(self, w3: "Web3", math_contract: "Contract") -> None:
web3/eth/async_eth.py CHANGED
@@ -720,19 +720,6 @@ class AsyncEth(BaseEth):
720
720
  mungers=[default_root_munger],
721
721
  )
722
722
 
723
- _subscribe_with_args: Method[
724
- Callable[
725
- [
726
- SubscriptionType,
727
- Optional[Union[LogsSubscriptionArg, bool]],
728
- ],
729
- Awaitable[HexStr],
730
- ]
731
- ] = Method(
732
- RPC.eth_subscribe,
733
- mungers=[default_root_munger],
734
- )
735
-
736
723
  async def subscribe(
737
724
  self,
738
725
  subscription_type: SubscriptionType,
@@ -745,6 +732,7 @@ class AsyncEth(BaseEth):
745
732
  handler: Optional[EthSubscriptionHandler] = None,
746
733
  handler_context: Optional[Dict[str, Any]] = None,
747
734
  label: Optional[str] = None,
735
+ parallelize: Optional[bool] = None,
748
736
  ) -> HexStr:
749
737
  if not isinstance(self.w3.provider, PersistentConnectionProvider):
750
738
  raise MethodNotSupported(
@@ -757,6 +745,7 @@ class AsyncEth(BaseEth):
757
745
  handler=handler,
758
746
  handler_context=handler_context or {},
759
747
  label=label,
748
+ parallelize=parallelize,
760
749
  )
761
750
  return await self.w3.subscription_manager.subscribe(sub)
762
751
 
web3/exceptions.py CHANGED
@@ -353,13 +353,20 @@ class PersistentConnectionClosedOK(PersistentConnectionError):
353
353
  """
354
354
 
355
355
 
356
- class SubscriptionProcessingFinished(Web3Exception):
356
+ class SubscriptionProcessingFinished(PersistentConnectionError):
357
357
  """
358
358
  Raised to alert the subscription manager that the processing of subscriptions
359
359
  has finished.
360
360
  """
361
361
 
362
362
 
363
+ class SubscriptionHandlerTaskException(TaskNotRunning):
364
+ """
365
+ Raised to alert the subscription manager that an exception occurred in the
366
+ subscription processing task.
367
+ """
368
+
369
+
363
370
  class Web3RPCError(Web3Exception):
364
371
  """
365
372
  Raised when a JSON-RPC response contains an error field.
web3/manager.py CHANGED
@@ -254,9 +254,9 @@ class RequestManager:
254
254
  """
255
255
  Context manager for making batch requests
256
256
  """
257
- if isinstance(self.provider, AutoProvider):
258
- self.provider = self.provider._get_active_provider(use_cache=True)
259
- if not isinstance(self.provider, (AsyncJSONBaseProvider, JSONBaseProvider)):
257
+ if not isinstance(
258
+ self.provider, (AsyncJSONBaseProvider, JSONBaseProvider, AutoProvider)
259
+ ):
260
260
  raise Web3TypeError("Batch requests are not supported by this provider.")
261
261
  return RequestBatcher(self.w3)
262
262
 
@@ -550,13 +550,10 @@ class RequestManager:
550
550
  else:
551
551
  # if not an active sub, skip processing and continue
552
552
  continue
553
- except TaskNotRunning:
553
+ except TaskNotRunning as e:
554
554
  await asyncio.sleep(0)
555
555
  self._provider._handle_listener_task_exceptions()
556
- self.logger.error(
557
- "Message listener background task has stopped unexpectedly. "
558
- "Stopping message stream."
559
- )
556
+ self.logger.error("Stopping message stream: %s", e.message)
560
557
  return
561
558
 
562
559
  async def _process_response(
@@ -16,6 +16,7 @@ from eth_utils.toolz import (
16
16
  )
17
17
 
18
18
  from web3.exceptions import (
19
+ BadResponseFormat,
19
20
  Web3ValueError,
20
21
  )
21
22
  from web3.middleware.base import (
@@ -77,7 +78,12 @@ def _apply_response_formatters(
77
78
  response, response_type, method_response_formatter(appropriate_response)
78
79
  )
79
80
 
80
- if response.get("result") is not None and method in result_formatters:
81
+ if not isinstance(response, dict):
82
+ raise BadResponseFormat(
83
+ "Malformed response: expected a valid JSON-RPC response object, got: "
84
+ "`{}`".format(response)
85
+ )
86
+ elif response.get("result") is not None and method in result_formatters:
81
87
  return _format_response("result", result_formatters[method])
82
88
  elif (
83
89
  # eth_subscription responses
web3/providers/auto.py CHANGED
@@ -3,6 +3,7 @@ from typing import (
3
3
  Any,
4
4
  Callable,
5
5
  Dict,
6
+ List,
6
7
  Optional,
7
8
  Sequence,
8
9
  Tuple,
@@ -21,9 +22,9 @@ from web3.exceptions import (
21
22
  CannotHandleRequest,
22
23
  )
23
24
  from web3.providers import (
24
- BaseProvider,
25
25
  HTTPProvider,
26
26
  IPCProvider,
27
+ JSONBaseProvider,
27
28
  LegacyWebSocketProvider,
28
29
  )
29
30
  from web3.types import (
@@ -35,7 +36,7 @@ HTTP_SCHEMES = {"http", "https"}
35
36
  WS_SCHEMES = {"ws", "wss"}
36
37
 
37
38
 
38
- def load_provider_from_environment() -> BaseProvider:
39
+ def load_provider_from_environment() -> Optional[JSONBaseProvider]:
39
40
  uri_string = URI(os.environ.get("WEB3_PROVIDER_URI", ""))
40
41
  if not uri_string:
41
42
  return None
@@ -45,7 +46,7 @@ def load_provider_from_environment() -> BaseProvider:
45
46
 
46
47
  def load_provider_from_uri(
47
48
  uri_string: URI, headers: Optional[Dict[str, Tuple[str, str]]] = None
48
- ) -> BaseProvider:
49
+ ) -> JSONBaseProvider:
49
50
  uri = urlparse(uri_string)
50
51
  if uri.scheme == "file":
51
52
  return IPCProvider(uri.path)
@@ -60,7 +61,7 @@ def load_provider_from_uri(
60
61
  )
61
62
 
62
63
 
63
- class AutoProvider(BaseProvider):
64
+ class AutoProvider(JSONBaseProvider):
64
65
  default_providers = (
65
66
  load_provider_from_environment,
66
67
  IPCProvider,
@@ -72,7 +73,7 @@ class AutoProvider(BaseProvider):
72
73
  def __init__(
73
74
  self,
74
75
  potential_providers: Optional[
75
- Sequence[Union[Callable[..., BaseProvider], Type[BaseProvider]]]
76
+ Sequence[Union[Callable[..., JSONBaseProvider], Type[JSONBaseProvider]]]
76
77
  ] = None,
77
78
  ) -> None:
78
79
  """
@@ -83,6 +84,7 @@ class AutoProvider(BaseProvider):
83
84
  in an attempt to find an active node. The list will default to
84
85
  :attribute:`default_providers`.
85
86
  """
87
+ super().__init__()
86
88
  if potential_providers:
87
89
  self._potential_providers = potential_providers
88
90
  else:
@@ -94,6 +96,14 @@ class AutoProvider(BaseProvider):
94
96
  except OSError:
95
97
  return self._proxy_request(method, params, use_cache=False)
96
98
 
99
+ def make_batch_request(
100
+ self, requests: List[Tuple[RPCEndpoint, Any]]
101
+ ) -> Union[List[RPCResponse], RPCResponse]:
102
+ try:
103
+ return self._proxy_batch_request(requests)
104
+ except OSError:
105
+ return self._proxy_batch_request(requests, use_cache=False)
106
+
97
107
  def is_connected(self, show_traceback: bool = False) -> bool:
98
108
  provider = self._get_active_provider(use_cache=True)
99
109
  return provider is not None and provider.is_connected(show_traceback)
@@ -110,7 +120,19 @@ class AutoProvider(BaseProvider):
110
120
 
111
121
  return provider.make_request(method, params)
112
122
 
113
- def _get_active_provider(self, use_cache: bool) -> Optional[BaseProvider]:
123
+ def _proxy_batch_request(
124
+ self, requests: List[Tuple[RPCEndpoint, Any]], use_cache: bool = True
125
+ ) -> Union[List[RPCResponse], RPCResponse]:
126
+ provider = self._get_active_provider(use_cache)
127
+ if provider is None:
128
+ raise CannotHandleRequest(
129
+ "Could not discover provider while making batch request: "
130
+ f"requests:{requests}\n"
131
+ )
132
+
133
+ return provider.make_batch_request(requests)
134
+
135
+ def _get_active_provider(self, use_cache: bool) -> Optional[JSONBaseProvider]:
114
136
  if use_cache and self._active_provider is not None:
115
137
  return self._active_provider
116
138
 
web3/providers/ipc.py CHANGED
@@ -59,7 +59,7 @@ def get_ipc_socket(ipc_path: str, timeout: float = 2.0) -> socket.socket:
59
59
  return sock
60
60
 
61
61
 
62
- class PersistantSocket:
62
+ class PersistentSocket:
63
63
  sock = None
64
64
 
65
65
  def __init__(self, ipc_path: str) -> None:
@@ -157,7 +157,7 @@ class IPCProvider(JSONBaseProvider):
157
157
 
158
158
  self.timeout = timeout
159
159
  self._lock = threading.Lock()
160
- self._socket = PersistantSocket(self.ipc_path)
160
+ self._socket = PersistentSocket(self.ipc_path)
161
161
 
162
162
  def __str__(self) -> str:
163
163
  return f"<{self.__class__.__name__} {self.ipc_path}>"
@@ -164,7 +164,7 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
164
164
  if cache_key != self._send_batch_func_cache[0]:
165
165
 
166
166
  async def send_func(
167
- requests: List[Tuple[RPCEndpoint, Any]]
167
+ requests: List[Tuple[RPCEndpoint, Any]],
168
168
  ) -> List[RPCRequest]:
169
169
  for mw in middleware:
170
170
  initialized = mw(async_w3)
@@ -376,11 +376,12 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
376
376
  ) -> None:
377
377
  # Puts a `TaskNotRunning` in appropriate queues to signal the end of the
378
378
  # listener task to any listeners relying on the queues.
379
+ message = "Message listener task has ended."
379
380
  self._request_processor._subscription_response_queue.put_nowait(
380
- TaskNotRunning(message_listener_task)
381
+ TaskNotRunning(message_listener_task, message=message)
381
382
  )
382
383
  self._request_processor._handler_subscription_queue.put_nowait(
383
- TaskNotRunning(message_listener_task)
384
+ TaskNotRunning(message_listener_task, message=message)
384
385
  )
385
386
 
386
387
  def _raise_stray_errors_from_cache(self) -> None:
@@ -5,6 +5,7 @@ from typing import (
5
5
  Any,
6
6
  List,
7
7
  Sequence,
8
+ Set,
8
9
  Union,
9
10
  cast,
10
11
  overload,
@@ -15,6 +16,7 @@ from eth_typing import (
15
16
  )
16
17
 
17
18
  from web3.exceptions import (
19
+ SubscriptionHandlerTaskException,
18
20
  SubscriptionProcessingFinished,
19
21
  TaskNotRunning,
20
22
  Web3TypeError,
@@ -50,19 +52,26 @@ class SubscriptionManager:
50
52
  logger: logging.Logger = logging.getLogger(
51
53
  "web3.providers.persistent.subscription_manager"
52
54
  )
53
- total_handler_calls: int = 0
54
55
 
55
56
  def __init__(self, w3: "AsyncWeb3") -> None:
56
57
  self._w3 = w3
57
58
  self._provider = cast("PersistentConnectionProvider", w3.provider)
58
59
  self._subscription_container = SubscriptionContainer()
59
60
 
61
+ # parallelize all subscription handler calls
62
+ self.parallelize = False
63
+ self.task_timeout = 1
64
+ # TODO: can remove quotes from type hints once Python 3.8 support is dropped
65
+ self._tasks: Set["asyncio.Task[None]"] = set()
66
+
60
67
  # share the subscription container with the request processor so it can separate
61
68
  # subscriptions into different queues based on ``sub._handler`` presence
62
69
  self._provider._request_processor._subscription_container = (
63
70
  self._subscription_container
64
71
  )
65
72
 
73
+ self.total_handler_calls: int = 0
74
+
66
75
  def _add_subscription(self, subscription: EthSubscription[Any]) -> None:
67
76
  self._subscription_container.add_subscription(subscription)
68
77
 
@@ -86,6 +95,35 @@ class SubscriptionManager:
86
95
  f"labels.\n label: {subscription._label}"
87
96
  )
88
97
 
98
+ # TODO: can remove quotes from type hints once Python 3.8 support is dropped
99
+ def _handler_task_callback(self, task: "asyncio.Task[None]") -> None:
100
+ """
101
+ Callback when a handler task completes. Similar to _message_listener_callback.
102
+ Puts handler exceptions into the queue to be raised in the main loop, else
103
+ removes the task from the set of active tasks.
104
+ """
105
+ if task.done() and not task.cancelled():
106
+ try:
107
+ task.result()
108
+ self._tasks.discard(task)
109
+ except Exception as e:
110
+ self.logger.exception("Subscription handler task raised an exception.")
111
+ self._provider._request_processor._handler_subscription_queue.put_nowait( # noqa: E501
112
+ SubscriptionHandlerTaskException(task, message=str(e))
113
+ )
114
+
115
+ async def _cleanup_remaining_tasks(self) -> None:
116
+ """Cancel and clean up all remaining tasks."""
117
+ if not self._tasks:
118
+ return
119
+
120
+ self.logger.debug("Cleaning up %d remaining tasks...", len(self._tasks))
121
+ for task in self._tasks:
122
+ if not task.done():
123
+ task.cancel()
124
+
125
+ self._tasks.clear()
126
+
89
127
  @property
90
128
  def subscriptions(self) -> List[EthSubscription[Any]]:
91
129
  return self._subscription_container.subscriptions
@@ -281,14 +319,23 @@ class SubscriptionManager:
281
319
  sub_id
282
320
  )
283
321
  if sub:
284
- await sub._handler(
285
- EthSubscriptionContext(
286
- self._w3,
287
- sub,
288
- formatted_sub_response["result"],
289
- **sub._handler_context,
290
- )
322
+ sub_context = EthSubscriptionContext(
323
+ self._w3,
324
+ sub,
325
+ formatted_sub_response["result"],
326
+ **sub._handler_context,
291
327
  )
328
+ if sub.parallelize is True or (
329
+ sub.parallelize is None and self.parallelize
330
+ ):
331
+ # run the handler in a task to allow parallel processing
332
+ task = asyncio.create_task(sub._handler(sub_context))
333
+ self._tasks.add(task)
334
+ task.add_done_callback(self._handler_task_callback)
335
+ else:
336
+ # await the handler in the main loop to ensure order
337
+ await sub._handler(sub_context)
338
+
292
339
  except SubscriptionProcessingFinished:
293
340
  if not run_forever:
294
341
  self.logger.info(
@@ -296,14 +343,20 @@ class SubscriptionManager:
296
343
  "Stopping subscription handling."
297
344
  )
298
345
  break
299
- except TaskNotRunning:
300
- await asyncio.sleep(0)
301
- self._provider._handle_listener_task_exceptions()
346
+ except SubscriptionHandlerTaskException:
302
347
  self.logger.error(
303
- "Message listener background task for the provider has stopped "
304
- "unexpectedly. Stopping subscription handling."
348
+ "An exception occurred in a subscription handler task. "
349
+ "Stopping subscription handling."
305
350
  )
351
+ await self._cleanup_remaining_tasks()
352
+ raise
353
+ except TaskNotRunning as e:
354
+ self.logger.error("Stopping subscription handling: %s", e.message)
355
+ self._provider._handle_listener_task_exceptions()
306
356
  break
307
357
 
308
358
  # no active handler subscriptions, clear the handler subscription queue
309
359
  self._provider._request_processor._reset_handler_subscription_queue()
360
+
361
+ if self._tasks:
362
+ await self._cleanup_remaining_tasks()
@@ -110,11 +110,14 @@ class EthSubscription(Generic[TSubscriptionResult]):
110
110
  handler: Optional[EthSubscriptionHandler] = None,
111
111
  handler_context: Optional[Dict[str, Any]] = None,
112
112
  label: Optional[str] = None,
113
+ parallelize: Optional[bool] = None,
113
114
  ) -> None:
114
115
  self._subscription_params = subscription_params
115
116
  self._handler = handler_wrapper(handler)
116
117
  self._handler_context = handler_context or {}
117
118
  self._label = label
119
+
120
+ self.parallelize = parallelize
118
121
  self.handler_call_count = 0
119
122
 
120
123
  @property
@@ -128,6 +131,7 @@ class EthSubscription(Generic[TSubscriptionResult]):
128
131
  handler: Optional[EthSubscriptionHandler] = None,
129
132
  handler_context: Optional[Dict[str, Any]] = None,
130
133
  label: Optional[str] = None,
134
+ parallelize: Optional[bool] = None,
131
135
  ) -> "EthSubscription[Any]":
132
136
  subscription_type = subscription_params[0]
133
137
  subscription_arg = (
@@ -135,7 +139,10 @@ class EthSubscription(Generic[TSubscriptionResult]):
135
139
  )
136
140
  if subscription_type == "newHeads":
137
141
  return NewHeadsSubscription(
138
- handler=handler, handler_context=handler_context, label=label
142
+ handler=handler,
143
+ handler_context=handler_context,
144
+ label=label,
145
+ parallelize=parallelize,
139
146
  )
140
147
  elif subscription_type == "logs":
141
148
  subscription_arg = subscription_arg or {}
@@ -144,6 +151,7 @@ class EthSubscription(Generic[TSubscriptionResult]):
144
151
  handler=handler,
145
152
  handler_context=handler_context,
146
153
  label=label,
154
+ parallelize=parallelize,
147
155
  )
148
156
  elif subscription_type == "newPendingTransactions":
149
157
  subscription_arg = subscription_arg or False
@@ -152,10 +160,14 @@ class EthSubscription(Generic[TSubscriptionResult]):
152
160
  handler=handler,
153
161
  handler_context=handler_context,
154
162
  label=label,
163
+ parallelize=parallelize,
155
164
  )
156
165
  elif subscription_type == "syncing":
157
166
  return SyncingSubscription(
158
- handler=handler, handler_context=handler_context, label=label
167
+ handler=handler,
168
+ handler_context=handler_context,
169
+ label=label,
170
+ parallelize=parallelize,
159
171
  )
160
172
  else:
161
173
  params = (
@@ -168,6 +180,7 @@ class EthSubscription(Generic[TSubscriptionResult]):
168
180
  handler=handler,
169
181
  handler_context=handler_context,
170
182
  label=label,
183
+ parallelize=parallelize,
171
184
  )
172
185
 
173
186
  @property
@@ -206,6 +219,7 @@ class LogsSubscription(EthSubscription[LogReceipt]):
206
219
  handler: LogsSubscriptionHandler = None,
207
220
  handler_context: Optional[Dict[str, Any]] = None,
208
221
  label: Optional[str] = None,
222
+ parallelize: Optional[bool] = None,
209
223
  ) -> None:
210
224
  self.address = address
211
225
  self.topics = topics
@@ -222,6 +236,7 @@ class LogsSubscription(EthSubscription[LogReceipt]):
222
236
  handler=handler,
223
237
  handler_context=handler_context,
224
238
  label=label,
239
+ parallelize=parallelize,
225
240
  )
226
241
 
227
242
 
@@ -237,12 +252,14 @@ class NewHeadsSubscription(EthSubscription[BlockData]):
237
252
  label: Optional[str] = None,
238
253
  handler: Optional[NewHeadsSubscriptionHandler] = None,
239
254
  handler_context: Optional[Dict[str, Any]] = None,
255
+ parallelize: Optional[bool] = None,
240
256
  ) -> None:
241
257
  super().__init__(
242
258
  subscription_params=("newHeads",),
243
259
  handler=handler,
244
260
  handler_context=handler_context,
245
261
  label=label,
262
+ parallelize=parallelize,
246
263
  )
247
264
 
248
265
 
@@ -261,6 +278,7 @@ class PendingTxSubscription(EthSubscription[Union[HexBytes, TxData]]):
261
278
  label: Optional[str] = None,
262
279
  handler: Optional[PendingTxSubscriptionHandler] = None,
263
280
  handler_context: Optional[Dict[str, Any]] = None,
281
+ parallelize: Optional[bool] = None,
264
282
  ) -> None:
265
283
  self.full_transactions = full_transactions
266
284
  super().__init__(
@@ -268,6 +286,7 @@ class PendingTxSubscription(EthSubscription[Union[HexBytes, TxData]]):
268
286
  handler=handler,
269
287
  handler_context=handler_context,
270
288
  label=label,
289
+ parallelize=parallelize,
271
290
  )
272
291
 
273
292
 
@@ -283,10 +302,12 @@ class SyncingSubscription(EthSubscription[SyncProgress]):
283
302
  label: Optional[str] = None,
284
303
  handler: Optional[SyncingSubscriptionHandler] = None,
285
304
  handler_context: Optional[Dict[str, Any]] = None,
305
+ parallelize: Optional[bool] = None,
286
306
  ) -> None:
287
307
  super().__init__(
288
308
  subscription_params=("syncing",),
289
309
  handler=handler,
290
310
  handler_context=handler_context,
291
311
  label=label,
312
+ parallelize=parallelize,
292
313
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: web3
3
- Version: 7.12.0
3
+ Version: 7.13.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
@@ -14,11 +14,11 @@ ens/specs/normalization_spec.json,sha256=8mmjBj4OoYCn7pD4P7hqKP_qy6rpYzpyRinSH3C
14
14
  web3/__init__.py,sha256=P11QAEV_GYoZq9ij8gDzFx5tKzJY2aMXG-keg2Lg1xs,1277
15
15
  web3/constants.py,sha256=eQLRQVMFPbgpOjjkPTMHkY-syncJuO-sPX5UrCSRjzQ,564
16
16
  web3/datastructures.py,sha256=J5rdpnuS10pKUfPYqcoorkDw-aHHZNrdiW-Bh7dVDwI,11514
17
- web3/exceptions.py,sha256=GMIrWTkYDR0jtvtdOlgl_s6fctTibW4Ytw4So5BY4uE,9584
17
+ web3/exceptions.py,sha256=9qWjvZM-snQTITs8FJbTMnVQygM80ciddwOkSgiioY8,9783
18
18
  web3/geth.py,sha256=xVBZWSksBo2ipesAN9V5hzDc_te7kU8ueicFdvpkSO4,7370
19
19
  web3/logs.py,sha256=ROs-mDMH_ZOecE7hfbWA5yp27G38FbLjX4lO_WtlZxQ,198
20
20
  web3/main.py,sha256=eVdSh7m_iBMf3au0Aj49TZ7NSaRbN1Ccsng9Fuu8dME,16162
21
- web3/manager.py,sha256=OgcUP8RxBZc_uU3HEqNOcVdj2BnlPQenxHXbWiJE1co,22784
21
+ web3/manager.py,sha256=jlHJoGdhFFSsZNTbdUXVakchJozxqrN_NPWp1gUSMgs,22588
22
22
  web3/method.py,sha256=BCYend146F5Q149VB2VN11_Z3x8y0lJZH8ShF_VxwV4,8682
23
23
  web3/module.py,sha256=CDlnDrrWzkCJtd3gzHZ972l-6En6IyFEWwB7TXkHHLM,5617
24
24
  web3/net.py,sha256=Y3vPzHWVFkfHEZoJxjDOt4tp5ERmZrMuyi4ZFOLmIeA,1562
@@ -89,7 +89,7 @@ web3/_utils/contract_sources/contract_data/storage_contract.py,sha256=ARz6J3Gmsn
89
89
  web3/_utils/contract_sources/contract_data/string_contract.py,sha256=sk6TWvzH7GkRxwioXFm2a7J99riySqipn2EQhfYdzLY,11228
90
90
  web3/_utils/contract_sources/contract_data/tuple_contracts.py,sha256=7RlKfKRVXhjJN1j7D4YlQM6BswK3c0VaSxcnPVwAgcg,23176
91
91
  web3/_utils/module_testing/__init__.py,sha256=Xr_S46cjr0mypD_Y4ZbeF1EJ-XWfNxWUks5ykhzN10c,485
92
- web3/_utils/module_testing/eth_module.py,sha256=g1gB35A97W2rCyWDLnM_9h_C0KuXAUbUSmReiHRK6AU,197426
92
+ web3/_utils/module_testing/eth_module.py,sha256=g4NW9m6jU5IXjWxp0Cl3UoVB3mC1FrHLt3ljztpZx4I,196504
93
93
  web3/_utils/module_testing/go_ethereum_admin_module.py,sha256=_c-6SyzZkfAJ-7ySXUpw9FEr4cg-ShRdAGSAHWanCtY,3406
94
94
  web3/_utils/module_testing/go_ethereum_debug_module.py,sha256=BP1UjK-5ewkYMilvW9jtZX5Mc9BGh3QlJWPXqDNWizU,4144
95
95
  web3/_utils/module_testing/go_ethereum_txpool_module.py,sha256=5f8XL8-2x3keyGRaITxMQYl9oQzjgqGn8zobB-j9BPs,1176
@@ -110,7 +110,7 @@ web3/contract/base_contract.py,sha256=vQVcne9luQ35eBheRh1Jc_jXOp2uDxIotKK9O1EQjQ
110
110
  web3/contract/contract.py,sha256=-TJJMjwybZmQo8-DtGhrjIr7TwVXFoiIsdMan1NFgQY,20562
111
111
  web3/contract/utils.py,sha256=QwJFbgojLKRb_7DrwDmXI2acwRk7zMNXHGvH5JaR1NI,18591
112
112
  web3/eth/__init__.py,sha256=qDLxOcHHIzzPD7xzwy6Wcs0lLPQieB7WN0Ax25ctit8,197
113
- web3/eth/async_eth.py,sha256=uuKOTRvI60r5zOj131Mbr28J6N7Tj2Hx4GJESMIoFu8,24759
113
+ web3/eth/async_eth.py,sha256=Uz-0W2rAk8tygbk5xJkffnAA8v-mneYrYsFePViGcTI,24535
114
114
  web3/eth/base_eth.py,sha256=UUH0Fw0HVa_mBEQ_CbCDO01yCVDsj33d8yOv7Oe-QD0,6905
115
115
  web3/eth/eth.py,sha256=zYhotz6GFRVl951oljXHnnlF1GJTgFlgJlA09Soji5k,20806
116
116
  web3/gas_strategies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -121,7 +121,7 @@ web3/middleware/attrdict.py,sha256=tIoMEZ3BkmEafnwitGY70o0GS9ShfwReDMxkHuvcOwI,2
121
121
  web3/middleware/base.py,sha256=jUY19tw6iiJenDprYqkTeIESd8qPcTvNALP3Vhp86qk,5728
122
122
  web3/middleware/buffered_gas_estimate.py,sha256=EmxUd-uO959UVroPsPKkl7oDa8Tw6N8BQLB6Urng5Eo,1647
123
123
  web3/middleware/filter.py,sha256=I09sSE_q_dhWX5_24KVWhVXZNevwViI7wucJBP4TZl4,22221
124
- web3/middleware/formatting.py,sha256=hqe5XQE1n5Fmj6riJp7i3oIoZkd-4ChQc7UK8f3HB6I,7567
124
+ web3/middleware/formatting.py,sha256=GPbJes2-ECQW5fbHllajGFDd4b58X-sKLef_DSnYA40,7793
125
125
  web3/middleware/gas_price_strategy.py,sha256=ZjZ6pe3z0mDGLZHYoFXp4_fZIePqukljEh9f4mZUyIA,3779
126
126
  web3/middleware/names.py,sha256=OBpsvCmcTItth4TcvUNUvcYmINnudtCHq3n6YO_BkNs,4309
127
127
  web3/middleware/proof_of_authority.py,sha256=0AT4jr5CmTdrvl8Jiy-WYy8IFDYBOEaesgHDwpn0c7M,1429
@@ -131,9 +131,9 @@ web3/middleware/stalecheck.py,sha256=oWRA69BGIbNGjHSnUVOBnoxOYJZYjzRzlqqL5RRlnzk
131
131
  web3/middleware/validation.py,sha256=QxActrJk_zsXXiwpadP2MUjZBS5E50OJOtUwVrm9XVo,4280
132
132
  web3/providers/__init__.py,sha256=YkcSzE9AubvSp-UfvJjyCrdepvziysbqeq2LT0ImDoc,936
133
133
  web3/providers/async_base.py,sha256=vCx4SAHPSACrRps4KZ36xgjAMQxKXqXsYB8jACodwWo,8241
134
- web3/providers/auto.py,sha256=Zx3CHKoRkmiw3Jte2BLNPiJAFd8rDXNGfA3XtxZvHgc,3465
134
+ web3/providers/auto.py,sha256=9Jacts6375zHEG969lm5LOdmnhG4kJFnh4jMYOySQWU,4300
135
135
  web3/providers/base.py,sha256=mTLfK5gZzykzfjVkb6QHROFAAeE6ZdS6J6IPfqZr_e4,6876
136
- web3/providers/ipc.py,sha256=pYx79r5aR4gC109Oun33UWd6HKg1bzBehr75i3lBC8g,6518
136
+ web3/providers/ipc.py,sha256=Rc0x4cW3NietQz0BjOygs78GzVGqgz0fHFZM6HalpVg,6518
137
137
  web3/providers/legacy_websocket.py,sha256=uQb5SmoFPFI809q_2iRhDEo5SkSW3T9tYXuf48stp9A,4744
138
138
  web3/providers/eth_tester/__init__.py,sha256=UggyBQdeAyjy1awATW1933jkJcpqqaUYUQEFAQnA2o0,163
139
139
  web3/providers/eth_tester/defaults.py,sha256=QQUdqqrkcN1AKW7WEY1A5RiPc_fmlHCLmdgB-5iY7Dc,12622
@@ -141,11 +141,11 @@ web3/providers/eth_tester/main.py,sha256=U19sNDeHs36A4IYQ0HFGyXdZvuXiYvoSMNWVuki
141
141
  web3/providers/eth_tester/middleware.py,sha256=JS-cjGF5BtF43dp-bP7QDv0RWyq1iqwiq81RhTAswjI,13730
142
142
  web3/providers/persistent/__init__.py,sha256=X7tFKJL5BXSwciq5_bRwGRB6bfdWBkIPPWMqCjXIKrA,411
143
143
  web3/providers/persistent/async_ipc.py,sha256=6HDKo9hIXhag3nyTbp6J-ZktPLnG-9iHCduQUGD7raM,5049
144
- web3/providers/persistent/persistent.py,sha256=79TP6mKOhUyxD3KBOEE2OeWido8qumuIl2pIiiPE-0k,19356
144
+ web3/providers/persistent/persistent.py,sha256=tM0Opg5i_oNlW_vmkqnzkAAPww36E5_jhonXDWfhc4Y,19444
145
145
  web3/providers/persistent/persistent_connection.py,sha256=NxxS-KeJhV07agg8CtJvmE-Ff-wLggQYpz4gdgVRDNU,3011
146
146
  web3/providers/persistent/request_processor.py,sha256=QLVn5MiNwDVsO9hsHPlkUH4zW4H74HRK-duPot4H4Yk,14141
147
147
  web3/providers/persistent/subscription_container.py,sha256=yd5pjjz_YnRLuUoxZUxt29Md1VUTemdUIBq8PCJre6Y,1734
148
- web3/providers/persistent/subscription_manager.py,sha256=T42LQzGs4iYvsKqvIqKSMo5OLz5Qpp4YG8sEBOcqV3s,11672
148
+ web3/providers/persistent/subscription_manager.py,sha256=QByJn3qfOT1Lt7L6BMUqNSeu_FajAGZRwLvawSajsic,13956
149
149
  web3/providers/persistent/utils.py,sha256=gfY7w1HB8xuE7OujSrbwWYjQuQ8nzRBoxoL8ESinqWM,1140
150
150
  web3/providers/persistent/websocket.py,sha256=STf31VNdwidMeAeeL1r5f8v3l66xChKkxZpnZzUiYO8,4577
151
151
  web3/providers/rpc/__init__.py,sha256=mObsuwjr7xyHnnRlwzsmbp2JgZdn2NXSSctvpye4AuQ,149
@@ -163,9 +163,9 @@ web3/utils/address.py,sha256=nzPLiWWCG9BqstDeDOcDwEpteJ8im6ywjLHKpd5akhw,1186
163
163
  web3/utils/async_exception_handling.py,sha256=OoKbLNwWcY9dxLCbOfxcQPSB1OxWraNqcw8V0ZX-JaQ,3173
164
164
  web3/utils/caching.py,sha256=miulUjLOjlOfTux8HWBklpRIa6_fVNTVFHIWcbZt27o,2591
165
165
  web3/utils/exception_handling.py,sha256=n-MtO5LNzJDVzHTzO6olzfb2_qEVtVRvink0ixswg-Y,2917
166
- web3/utils/subscriptions.py,sha256=RnqwQL3ekkMyCrbx-jVf6EaEkihyXTbb1LBonBHAJ_g,8617
167
- web3-7.12.0.dist-info/licenses/LICENSE,sha256=ENGC4gSn0kYaC_mlaXOEwCKmA6W7Z9MeSemc5O2k-h0,1095
168
- web3-7.12.0.dist-info/METADATA,sha256=aYgiaFPo3N-8UA9Hr6ITnmEjbXd-FafOwsCRKb56c-c,5621
169
- web3-7.12.0.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
170
- web3-7.12.0.dist-info/top_level.txt,sha256=iwupuJh7wgypXrpk_awszyri3TahRr5vxSphNyvt1bU,9
171
- web3-7.12.0.dist-info/RECORD,,
166
+ web3/utils/subscriptions.py,sha256=XF0bN_OjIkweSTQmB0U0nMJrLCeNYYuukoUFiV5skV0,9340
167
+ web3-7.13.0.dist-info/licenses/LICENSE,sha256=ENGC4gSn0kYaC_mlaXOEwCKmA6W7Z9MeSemc5O2k-h0,1095
168
+ web3-7.13.0.dist-info/METADATA,sha256=8-k-l2hjPirh12SotNzYaXchRfwcPo2GJCSLB5gVs3s,5621
169
+ web3-7.13.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
170
+ web3-7.13.0.dist-info/top_level.txt,sha256=iwupuJh7wgypXrpk_awszyri3TahRr5vxSphNyvt1bU,9
171
+ web3-7.13.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.8.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5