web3 6.18.0__py3-none-any.whl → 6.19.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.
@@ -193,6 +193,12 @@ class WebsocketMessageStreamMock:
193
193
  self.messages = deque(messages) if messages else deque()
194
194
  self.raise_exception = raise_exception
195
195
 
196
+ def __await__(self) -> Generator[Any, Any, "Self"]:
197
+ async def __async_init__() -> "Self":
198
+ return self
199
+
200
+ return __async_init__().__await__()
201
+
196
202
  def __aiter__(self) -> "Self":
197
203
  return self
198
204
 
@@ -205,6 +211,13 @@ class WebsocketMessageStreamMock:
205
211
 
206
212
  return self.messages.popleft()
207
213
 
214
+ @staticmethod
215
+ async def pong() -> Literal[False]:
216
+ return False
217
+
218
+ async def connect(self) -> None:
219
+ pass
220
+
208
221
  async def send(self, data: bytes) -> None:
209
222
  pass
210
223
 
web3/exceptions.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import datetime
2
2
  import time
3
3
  from typing import (
4
+ TYPE_CHECKING,
4
5
  Any,
5
6
  Dict,
6
7
  Optional,
@@ -15,6 +16,9 @@ from web3.types import (
15
16
  BlockData,
16
17
  )
17
18
 
19
+ if TYPE_CHECKING:
20
+ import asyncio
21
+
18
22
 
19
23
  class Web3Exception(Exception):
20
24
  """
@@ -341,7 +345,21 @@ class BadResponseFormat(Web3Exception):
341
345
  Raised when a JSON-RPC response comes back in an unexpected format
342
346
  """
343
347
 
344
- pass
348
+
349
+ class TaskNotRunning(Web3Exception):
350
+ """
351
+ Used to signal between asyncio contexts that a task that is being awaited
352
+ is not currently running.
353
+ """
354
+
355
+ def __init__(
356
+ self, task: "asyncio.Task[Any]", message: Optional[str] = None
357
+ ) -> None:
358
+ self.task = task
359
+ if message is None:
360
+ message = f"Task {task} is not running."
361
+ self.message = message
362
+ super().__init__(message)
345
363
 
346
364
 
347
365
  class MethodUnavailable(Web3Exception):
web3/main.py CHANGED
@@ -573,12 +573,9 @@ class _PersistentConnectionWeb3(AsyncWeb3):
573
573
 
574
574
  # async for w3 in w3.persistent_websocket(provider)
575
575
  async def __aiter__(self) -> AsyncIterator[Self]:
576
- if not await self.provider.is_connected():
577
- await self.provider.connect()
578
-
576
+ provider = self.provider
579
577
  while True:
580
- try:
581
- yield self
582
- except Exception:
583
- # provider should handle connection / reconnection
584
- continue
578
+ await provider.connect()
579
+ yield self
580
+ provider.logger.error("Connection interrupted, attempting to reconnect...")
581
+ await provider.disconnect()
web3/manager.py CHANGED
@@ -35,6 +35,7 @@ from web3.exceptions import (
35
35
  BadResponseFormat,
36
36
  MethodUnavailable,
37
37
  ProviderConnectionError,
38
+ TaskNotRunning,
38
39
  )
39
40
  from web3.middleware import (
40
41
  abi_middleware,
@@ -377,14 +378,24 @@ class RequestManager:
377
378
  raise ProviderConnectionError("No listener found for websocket connection.")
378
379
 
379
380
  while True:
380
- response = await self._request_processor.pop_raw_response(subscription=True)
381
- if (
382
- response is not None
383
- and response.get("params", {}).get("subscription")
384
- in self._request_processor.active_subscriptions
385
- ):
386
- # if response is an active subscription response, process it
387
- yield await self._process_ws_response(response)
381
+ try:
382
+ response = await self._request_processor.pop_raw_response(
383
+ subscription=True
384
+ )
385
+ if (
386
+ response is not None
387
+ and response.get("params", {}).get("subscription")
388
+ in self._request_processor.active_subscriptions
389
+ ):
390
+ # if response is an active subscription response, process it
391
+ yield await self._process_ws_response(response)
392
+ except TaskNotRunning:
393
+ self._provider._handle_listener_task_exceptions()
394
+ self.logger.error(
395
+ "Message listener background task has stopped unexpectedly. "
396
+ "Stopping message stream."
397
+ )
398
+ raise StopAsyncIteration
388
399
 
389
400
  async def _process_ws_response(self, response: RPCResponse) -> RPCResponse:
390
401
  provider = cast(PersistentConnectionProvider, self._provider)
@@ -7,16 +7,30 @@ from typing import (
7
7
  Optional,
8
8
  )
9
9
 
10
- from websockets.legacy.client import (
10
+ from websockets import (
11
+ ConnectionClosed,
11
12
  WebSocketClientProtocol,
13
+ WebSocketException,
12
14
  )
13
15
 
16
+ from web3._utils.caching import (
17
+ generate_cache_key,
18
+ )
19
+ from web3.exceptions import (
20
+ ProviderConnectionError,
21
+ TaskNotRunning,
22
+ TimeExhausted,
23
+ )
14
24
  from web3.providers.async_base import (
15
25
  AsyncJSONBaseProvider,
16
26
  )
17
27
  from web3.providers.websocket.request_processor import (
18
28
  RequestProcessor,
19
29
  )
30
+ from web3.types import (
31
+ RPCId,
32
+ RPCResponse,
33
+ )
20
34
 
21
35
  DEFAULT_PERSISTENT_CONNECTION_TIMEOUT = 50.0
22
36
 
@@ -26,6 +40,8 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
26
40
  has_persistent_connection = True
27
41
  endpoint_uri: Optional[str] = None
28
42
 
43
+ _max_connection_retries: int = 5
44
+
29
45
  _ws: Optional[WebSocketClientProtocol] = None
30
46
  _request_processor: RequestProcessor
31
47
  _message_listener_task: Optional["asyncio.Task[None]"] = None
@@ -36,6 +52,7 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
36
52
  request_timeout: float = DEFAULT_PERSISTENT_CONNECTION_TIMEOUT,
37
53
  subscription_response_queue_size: int = 500,
38
54
  request_information_cache_size: int = 500,
55
+ silence_listener_task_exceptions: bool = False,
39
56
  ) -> None:
40
57
  super().__init__()
41
58
  self._request_processor = RequestProcessor(
@@ -44,12 +61,154 @@ class PersistentConnectionProvider(AsyncJSONBaseProvider, ABC):
44
61
  request_information_cache_size=request_information_cache_size,
45
62
  )
46
63
  self.request_timeout = request_timeout
64
+ self.silence_listener_task_exceptions = silence_listener_task_exceptions
47
65
 
48
66
  async def connect(self) -> None:
49
- raise NotImplementedError("Must be implemented by subclasses")
67
+ _connection_attempts = 0
68
+ _backoff_rate_change = 1.75
69
+ _backoff_time = 1.75
70
+
71
+ while _connection_attempts != self._max_connection_retries:
72
+ try:
73
+ _connection_attempts += 1
74
+ self.logger.info(f"Connecting to: {self.endpoint_uri}")
75
+ await self._provider_specific_connect()
76
+ self._message_listener_task = asyncio.create_task(
77
+ self._message_listener()
78
+ )
79
+ self._message_listener_task.add_done_callback(
80
+ self._message_listener_callback
81
+ )
82
+ self.logger.info(f"Successfully connected to: {self.endpoint_uri}")
83
+ break
84
+ except (WebSocketException, OSError) as e:
85
+ if _connection_attempts == self._max_connection_retries:
86
+ raise ProviderConnectionError(
87
+ f"Could not connect to: {self.endpoint_uri}. "
88
+ f"Retries exceeded max of {self._max_connection_retries}."
89
+ ) from e
90
+ self.logger.info(
91
+ f"Could not connect to: {self.endpoint_uri}. "
92
+ f"Retrying in {round(_backoff_time, 1)} seconds.",
93
+ exc_info=True,
94
+ )
95
+ await asyncio.sleep(_backoff_time)
96
+ _backoff_time *= _backoff_rate_change
50
97
 
51
98
  async def disconnect(self) -> None:
99
+ try:
100
+ if self._message_listener_task:
101
+ self._message_listener_task.cancel()
102
+ await self._message_listener_task
103
+ except (asyncio.CancelledError, StopAsyncIteration, ConnectionClosed):
104
+ pass
105
+ finally:
106
+ self._message_listener_task = None
107
+ self.logger.info("Message listener background task successfully shut down.")
108
+
109
+ await self._provider_specific_disconnect()
110
+ self._request_processor.clear_caches()
111
+ self.logger.info(f"Successfully disconnected from: {self.endpoint_uri}")
112
+
113
+ # -- private methods -- #
114
+
115
+ async def _provider_specific_connect(self) -> None:
52
116
  raise NotImplementedError("Must be implemented by subclasses")
53
117
 
54
- async def _ws_message_listener(self) -> None:
118
+ async def _provider_specific_disconnect(self) -> None:
55
119
  raise NotImplementedError("Must be implemented by subclasses")
120
+
121
+ async def _provider_specific_message_listener(self) -> None:
122
+ raise NotImplementedError("Must be implemented by subclasses")
123
+
124
+ def _message_listener_callback(
125
+ self, message_listener_task: "asyncio.Task[None]"
126
+ ) -> None:
127
+ # Puts a `TaskNotRunning` in the queue to signal the end of the listener task
128
+ # to any running subscription streams that are awaiting a response.
129
+ self._request_processor._subscription_response_queue.put_nowait(
130
+ TaskNotRunning(message_listener_task)
131
+ )
132
+
133
+ async def _message_listener(self) -> None:
134
+ self.logger.info(
135
+ f"{self.__class__.__qualname__} listener background task started. Storing "
136
+ "all messages in appropriate request processor queues / caches to be "
137
+ "processed."
138
+ )
139
+ while True:
140
+ # the use of sleep(0) seems to be the most efficient way to yield control
141
+ # back to the event loop to share the loop with other tasks.
142
+ await asyncio.sleep(0)
143
+ try:
144
+ await self._provider_specific_message_listener()
145
+ except Exception as e:
146
+ if not self.silence_listener_task_exceptions:
147
+ raise e
148
+ else:
149
+ self._error_log_listener_task_exception(e)
150
+
151
+ def _error_log_listener_task_exception(self, e: Exception) -> None:
152
+ """
153
+ When silencing listener task exceptions, this method is used to log the
154
+ exception and keep the listener task alive. Override this method to fine-tune
155
+ error logging behavior for the implementation class.
156
+ """
157
+ self.logger.error(
158
+ "Exception caught in listener, error logging and keeping "
159
+ "listener background task alive."
160
+ f"\n error={e.__class__.__name__}: {e}"
161
+ )
162
+
163
+ def _handle_listener_task_exceptions(self) -> None:
164
+ """
165
+ Should be called every time a `PersistentConnectionProvider` is polling for
166
+ messages in the main loop. If the message listener task has completed and an
167
+ exception was recorded, raise the exception in the main loop.
168
+ """
169
+ msg_listener_task = getattr(self, "_message_listener_task", None)
170
+ if (
171
+ msg_listener_task
172
+ and msg_listener_task.done()
173
+ and msg_listener_task.exception()
174
+ ):
175
+ raise msg_listener_task.exception()
176
+
177
+ async def _get_response_for_request_id(
178
+ self, request_id: RPCId, timeout: Optional[float] = None
179
+ ) -> RPCResponse:
180
+ if timeout is None:
181
+ timeout = self.request_timeout
182
+
183
+ async def _match_response_id_to_request_id() -> RPCResponse:
184
+ request_cache_key = generate_cache_key(request_id)
185
+
186
+ while True:
187
+ # check if an exception was recorded in the listener task and raise it
188
+ # in the main loop if so
189
+ self._handle_listener_task_exceptions()
190
+
191
+ if request_cache_key in self._request_processor._request_response_cache:
192
+ self.logger.debug(
193
+ f"Popping response for id {request_id} from cache."
194
+ )
195
+ popped_response = await self._request_processor.pop_raw_response(
196
+ cache_key=request_cache_key,
197
+ )
198
+ return popped_response
199
+ else:
200
+ await asyncio.sleep(0)
201
+
202
+ try:
203
+ # Add the request timeout around the while loop that checks the request
204
+ # cache. If the request is not in the cache within the request_timeout,
205
+ # raise ``TimeExhausted``.
206
+ return await asyncio.wait_for(_match_response_id_to_request_id(), timeout)
207
+ except asyncio.TimeoutError:
208
+ raise TimeExhausted(
209
+ f"Timed out waiting for response with request id `{request_id}` after "
210
+ f"{self.request_timeout} second(s). This may be due to the provider "
211
+ "not returning a response with the same id that was sent in the "
212
+ "request or an exception raised during the request was caught and "
213
+ "allowed to continue."
214
+ )
@@ -2,19 +2,26 @@ import asyncio
2
2
  from copy import (
3
3
  copy,
4
4
  )
5
+ import sys
5
6
  from typing import (
6
7
  TYPE_CHECKING,
7
8
  Any,
8
9
  Callable,
9
10
  Dict,
11
+ Generic,
10
12
  Optional,
11
13
  Tuple,
14
+ TypeVar,
15
+ Union,
12
16
  )
13
17
 
14
18
  from web3._utils.caching import (
15
19
  RequestInformation,
16
20
  generate_cache_key,
17
21
  )
22
+ from web3.exceptions import (
23
+ TaskNotRunning,
24
+ )
18
25
  from web3.types import (
19
26
  RPCEndpoint,
20
27
  RPCResponse,
@@ -28,6 +35,34 @@ if TYPE_CHECKING:
28
35
  PersistentConnectionProvider,
29
36
  )
30
37
 
38
+ T = TypeVar("T")
39
+
40
+ # TODO: This is an ugly hack for python 3.8. Remove this after we drop support for it
41
+ # and use `asyncio.Queue[T]` type directly in the `TaskReliantQueue` class.
42
+ if sys.version_info >= (3, 9):
43
+
44
+ class _TaskReliantQueue(asyncio.Queue[T], Generic[T]):
45
+ pass
46
+
47
+ else:
48
+
49
+ class _TaskReliantQueue(asyncio.Queue, Generic[T]): # type: ignore
50
+ pass
51
+
52
+
53
+ class TaskReliantQueue(_TaskReliantQueue[T]):
54
+ """
55
+ A queue that relies on a task to be running to process items in the queue.
56
+ """
57
+
58
+ async def get(self) -> T:
59
+ item = await super().get()
60
+ if isinstance(item, Exception):
61
+ # if the item is an exception, raise it so the task can handle this case
62
+ # more gracefully
63
+ raise item
64
+ return item
65
+
31
66
 
32
67
  class RequestProcessor:
33
68
  _subscription_queue_synced_with_ws_stream: bool = False
@@ -41,9 +76,9 @@ class RequestProcessor:
41
76
  self._provider = provider
42
77
 
43
78
  self._request_response_cache: SimpleCache = SimpleCache(500)
44
- self._subscription_response_queue: asyncio.Queue[RPCResponse] = asyncio.Queue(
45
- maxsize=subscription_response_queue_size
46
- )
79
+ self._subscription_response_queue: TaskReliantQueue[
80
+ Union[RPCResponse, TaskNotRunning]
81
+ ] = TaskReliantQueue(maxsize=subscription_response_queue_size)
47
82
  self._request_information_cache: SimpleCache = SimpleCache(
48
83
  request_information_cache_size
49
84
  )
@@ -203,7 +238,7 @@ class RequestProcessor:
203
238
  ) -> None:
204
239
  if subscription:
205
240
  if self._subscription_response_queue.full():
206
- self._provider.logger.info(
241
+ self._provider.logger.debug(
207
242
  "Subscription queue is full. Waiting for provider to consume "
208
243
  "messages before caching."
209
244
  )
@@ -276,6 +311,6 @@ class RequestProcessor:
276
311
 
277
312
  self._request_information_cache.clear()
278
313
  self._request_response_cache.clear()
279
- self._subscription_response_queue = asyncio.Queue(
314
+ self._subscription_response_queue = TaskReliantQueue(
280
315
  maxsize=self._subscription_response_queue.maxsize
281
316
  )
@@ -22,12 +22,8 @@ from websockets.exceptions import (
22
22
  WebSocketException,
23
23
  )
24
24
 
25
- from web3._utils.caching import (
26
- generate_cache_key,
27
- )
28
25
  from web3.exceptions import (
29
26
  ProviderConnectionError,
30
- TimeExhausted,
31
27
  Web3ValidationError,
32
28
  )
33
29
  from web3.providers.persistent import (
@@ -35,7 +31,6 @@ from web3.providers.persistent import (
35
31
  )
36
32
  from web3.types import (
37
33
  RPCEndpoint,
38
- RPCId,
39
34
  RPCResponse,
40
35
  )
41
36
 
@@ -59,7 +54,6 @@ def get_default_endpoint() -> URI:
59
54
  class WebsocketProviderV2(PersistentConnectionProvider):
60
55
  logger = logging.getLogger("web3.providers.WebsocketProviderV2")
61
56
  is_async: bool = True
62
- _max_connection_retries: int = 5
63
57
 
64
58
  def __init__(
65
59
  self,
@@ -69,16 +63,16 @@ class WebsocketProviderV2(PersistentConnectionProvider):
69
63
  # `PersistentConnectionProvider` kwargs can be passed through
70
64
  **kwargs: Any,
71
65
  ) -> None:
72
- self.endpoint_uri = URI(endpoint_uri)
73
- if self.endpoint_uri is None:
74
- self.endpoint_uri = get_default_endpoint()
66
+ self.endpoint_uri = (
67
+ URI(endpoint_uri) if endpoint_uri is not None else get_default_endpoint()
68
+ )
75
69
 
76
70
  if not any(
77
71
  self.endpoint_uri.startswith(prefix)
78
72
  for prefix in VALID_WEBSOCKET_URI_PREFIXES
79
73
  ):
80
74
  raise Web3ValidationError(
81
- "Websocket endpoint uri must begin with 'ws://' or 'wss://': "
75
+ "WebSocket endpoint uri must begin with 'ws://' or 'wss://': "
82
76
  f"{self.endpoint_uri}"
83
77
  )
84
78
 
@@ -93,12 +87,13 @@ class WebsocketProviderV2(PersistentConnectionProvider):
93
87
  )
94
88
 
95
89
  self.websocket_kwargs = merge(DEFAULT_WEBSOCKET_KWARGS, websocket_kwargs or {})
96
- self.silence_listener_task_exceptions = silence_listener_task_exceptions
97
90
 
98
- super().__init__(**kwargs)
91
+ super().__init__(
92
+ silence_listener_task_exceptions=silence_listener_task_exceptions, **kwargs
93
+ )
99
94
 
100
95
  def __str__(self) -> str:
101
- return f"Websocket connection: {self.endpoint_uri}"
96
+ return f"WebSocket connection: {self.endpoint_uri}"
102
97
 
103
98
  async def is_connected(self, show_traceback: bool = False) -> bool:
104
99
  if not self._ws:
@@ -115,47 +110,13 @@ class WebsocketProviderV2(PersistentConnectionProvider):
115
110
  ) from e
116
111
  return False
117
112
 
118
- async def connect(self) -> None:
119
- _connection_attempts = 0
120
- _backoff_rate_change = 1.75
121
- _backoff_time = 1.75
122
-
123
- while _connection_attempts != self._max_connection_retries:
124
- try:
125
- _connection_attempts += 1
126
- self._ws = await connect(self.endpoint_uri, **self.websocket_kwargs)
127
- self._message_listener_task = asyncio.create_task(
128
- self._ws_message_listener()
129
- )
130
- break
131
- except WebSocketException as e:
132
- if _connection_attempts == self._max_connection_retries:
133
- raise ProviderConnectionError(
134
- f"Could not connect to endpoint: {self.endpoint_uri}. "
135
- f"Retries exceeded max of {self._max_connection_retries}."
136
- ) from e
137
- self.logger.info(
138
- f"Could not connect to endpoint: {self.endpoint_uri}. Retrying in "
139
- f"{round(_backoff_time, 1)} seconds.",
140
- exc_info=True,
141
- )
142
- await asyncio.sleep(_backoff_time)
143
- _backoff_time *= _backoff_rate_change
113
+ async def _provider_specific_connect(self) -> None:
114
+ self._ws = await connect(self.endpoint_uri, **self.websocket_kwargs)
144
115
 
145
- async def disconnect(self) -> None:
116
+ async def _provider_specific_disconnect(self) -> None:
146
117
  if self._ws is not None and not self._ws.closed:
147
118
  await self._ws.close()
148
119
  self._ws = None
149
- self.logger.debug(
150
- f'Successfully disconnected from endpoint: "{self.endpoint_uri}'
151
- )
152
-
153
- try:
154
- self._message_listener_task.cancel()
155
- await self._message_listener_task
156
- except (asyncio.CancelledError, StopAsyncIteration):
157
- pass
158
- self._request_processor.clear_caches()
159
120
 
160
121
  async def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
161
122
  request_data = self.encode_rpc_request(method, params)
@@ -174,69 +135,12 @@ class WebsocketProviderV2(PersistentConnectionProvider):
174
135
 
175
136
  return response
176
137
 
177
- async def _get_response_for_request_id(self, request_id: RPCId) -> RPCResponse:
178
- async def _match_response_id_to_request_id() -> RPCResponse:
179
- request_cache_key = generate_cache_key(request_id)
180
-
181
- while True:
182
- # sleep(0) here seems to be the most efficient way to yield control
183
- # back to the event loop while waiting for the response to be in the
184
- # queue.
185
- await asyncio.sleep(0)
186
-
187
- if request_cache_key in self._request_processor._request_response_cache:
188
- self.logger.debug(
189
- f"Popping response for id {request_id} from cache."
190
- )
191
- popped_response = await self._request_processor.pop_raw_response(
192
- cache_key=request_cache_key,
193
- )
194
- return popped_response
195
-
196
- try:
197
- # Add the request timeout around the while loop that checks the request
198
- # cache and tried to recv(). If the request is neither in the cache, nor
199
- # received within the request_timeout, raise ``TimeExhausted``.
200
- return await asyncio.wait_for(
201
- _match_response_id_to_request_id(), self.request_timeout
202
- )
203
- except asyncio.TimeoutError:
204
- raise TimeExhausted(
205
- f"Timed out waiting for response with request id `{request_id}` after "
206
- f"{self.request_timeout} second(s). This may be due to the provider "
207
- "not returning a response with the same id that was sent in the "
208
- "request or an exception raised during the request was caught and "
209
- "allowed to continue."
210
- )
211
-
212
- async def _ws_message_listener(self) -> None:
213
- self.logger.info(
214
- "Websocket listener background task started. Storing all messages in "
215
- "appropriate request processor queues / caches to be processed."
216
- )
217
- while True:
218
- # the use of sleep(0) seems to be the most efficient way to yield control
219
- # back to the event loop to share the loop with other tasks.
138
+ async def _provider_specific_message_listener(self) -> None:
139
+ async for raw_message in self._ws:
220
140
  await asyncio.sleep(0)
221
141
 
222
- try:
223
- async for raw_message in self._ws:
224
- await asyncio.sleep(0)
225
-
226
- response = json.loads(raw_message)
227
- subscription = response.get("method") == "eth_subscription"
228
- await self._request_processor.cache_raw_response(
229
- response, subscription=subscription
230
- )
231
- except Exception as e:
232
- if not self.silence_listener_task_exceptions:
233
- loop = asyncio.get_event_loop()
234
- for task in asyncio.all_tasks(loop=loop):
235
- task.cancel()
236
- raise e
237
-
238
- self.logger.error(
239
- "Exception caught in listener, error logging and keeping "
240
- "listener background task alive."
241
- f"\n error={e.__class__.__name__}: {e}"
242
- )
142
+ response = json.loads(raw_message)
143
+ subscription = response.get("method") == "eth_subscription"
144
+ await self._request_processor.cache_raw_response(
145
+ response, subscription=subscription
146
+ )
@@ -27,7 +27,7 @@ class Deployer:
27
27
  f"Expected a Package object, instead received {type(package)}."
28
28
  )
29
29
  self.package = package
30
- self.strategies = {} # type: Dict[str, Callable[[Package], Package]]
30
+ self.strategies: Dict[str, Callable[[Package], Package]] = {}
31
31
 
32
32
  def deploy(self, contract_type: ContractName, *args: Any, **kwargs: Any) -> Package:
33
33
  factory = self.package.get_contract_factory(contract_type)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: web3
3
- Version: 6.18.0
3
+ Version: 6.19.0
4
4
  Summary: web3.py
5
5
  Home-page: https://github.com/ethereum/web3.py
6
6
  Author: The Ethereum Foundation
@@ -117,11 +117,11 @@ ethpm/validation/uri.py,sha256=JtNfDghEU-8yDoETIbEZnamlpFGF1fAQ-tdJQhqn7mg,4873
117
117
  web3/__init__.py,sha256=tieKn-7-iyxdwx_tI7eUGWBpSkawfI2_3pCnwh8PRP4,972
118
118
  web3/constants.py,sha256=eQLRQVMFPbgpOjjkPTMHkY-syncJuO-sPX5UrCSRjzQ,564
119
119
  web3/datastructures.py,sha256=5SuX36p-hGuiK3RwnG8yVsgROvkqzHdDKfTGSzghSy0,9234
120
- web3/exceptions.py,sha256=u0qTr7mS9wEmh-0jSfXNlEzJ-Sfigr4MwF6HxE7_wUw,6904
120
+ web3/exceptions.py,sha256=3c0uRBiKvRJCSQUALYDCjjsjcyqx_XJM4_oQBXKrBrs,7390
121
121
  web3/geth.py,sha256=IXdSkRg5n8Nv6KXdY94HwEcFnixOosOHoNanvJNA5rk,13676
122
122
  web3/logs.py,sha256=ROs-mDMH_ZOecE7hfbWA5yp27G38FbLjX4lO_WtlZxQ,198
123
- web3/main.py,sha256=3bEGj9n4E9dr40RZO2RC0SI6yGeRDJzqHyv98-E6ICw,15893
124
- web3/manager.py,sha256=OO32G09QT4j5-p6x5ZxYT82Z5HMnyCm0G1PqPPPHbqA,16212
123
+ web3/main.py,sha256=bPMEBxLfoA4VeLIeAO4V7oXXujHieBQHpDTA3eMHf_I,15854
124
+ web3/manager.py,sha256=TI705zxN2ZEnqJoA3EwWoiYnnw9B642c9rHndIg0BtA,16643
125
125
  web3/method.py,sha256=KKtQR9YjzSWWzl_gsLX0P4JqOEJnCzhN6naM9GOQvm0,8349
126
126
  web3/module.py,sha256=hoPoBaH992SHm_DRA7yxYZTFy61RQJ7_NZTU-AkZmds,4659
127
127
  web3/net.py,sha256=Y3vPzHWVFkfHEZoJxjDOt4tp5ERmZrMuyi4ZFOLmIeA,1562
@@ -195,7 +195,7 @@ web3/_utils/module_testing/eth_module.py,sha256=JQ0XAF5GlvpHn3oeAi2DfltJdCZwHk7J
195
195
  web3/_utils/module_testing/go_ethereum_admin_module.py,sha256=_c-6SyzZkfAJ-7ySXUpw9FEr4cg-ShRdAGSAHWanCtY,3406
196
196
  web3/_utils/module_testing/go_ethereum_personal_module.py,sha256=KzYEcAs_6Ud_gbu6YMOC6HijTdNFiz-qogMCViedmY0,11536
197
197
  web3/_utils/module_testing/go_ethereum_txpool_module.py,sha256=5f8XL8-2x3keyGRaITxMQYl9oQzjgqGn8zobB-j9BPs,1176
198
- web3/_utils/module_testing/module_testing_utils.py,sha256=sfsIUGtVOntKHh-HBiY4FaWvsVsy9UQkCEmhaTnqQSc,5987
198
+ web3/_utils/module_testing/module_testing_utils.py,sha256=_BV5xITzHC6HkOL3GD6bCJ-vhEsPQt2iSpY9S_SWXYo,6290
199
199
  web3/_utils/module_testing/net_module.py,sha256=ifUTC-5fTcQbwpm0X09OdD5RSPnn00T8klFeYe8tTm4,1272
200
200
  web3/_utils/module_testing/persistent_connection_provider.py,sha256=2NFjp0ZShOt_D5gmcfrc2ua57mRyeFSZpkqtPgCNUgM,16620
201
201
  web3/_utils/module_testing/web3_module.py,sha256=Y4lYglg_kbrpfwGfjekv52h4B7DaWa3uS15KGrCKL7c,9613
@@ -243,17 +243,17 @@ web3/providers/async_rpc.py,sha256=1tf72qPH8A3IW2ZJus9nORL-PfPgRtmj1YRFASVWyuM,2
243
243
  web3/providers/auto.py,sha256=-dS_-2nhg2jOA432P0w3Ul3NUIso8rTl4uGUGo0XBw0,3447
244
244
  web3/providers/base.py,sha256=qASmfdhXhD2FSk2Uk8z-8NxVL4i42uJNoUlwRDzQpgI,4187
245
245
  web3/providers/ipc.py,sha256=xFWT6cY9emTnFMuIQFrmQ0DJMQSMoQtaztD7MTTVniI,6374
246
- web3/providers/persistent.py,sha256=EHNmRso_-nvNLnTGF6jgmb_KRU29LgMfVU4mFt5RYBw,1668
246
+ web3/providers/persistent.py,sha256=L9Cgs3RxcUmplo3-mnDl9U0VlzMWfXZSVMWtWMjS0bY,8376
247
247
  web3/providers/rpc.py,sha256=w3XA8lhufp_tcGCqocRwi2DDt8j3fj0hoZGk0dfF0u0,2686
248
248
  web3/providers/eth_tester/__init__.py,sha256=J6wazY3hQySsUfpFgwCXbEMo-CGEZjRo11RCg4UXKmA,83
249
249
  web3/providers/eth_tester/defaults.py,sha256=Ri_WPJT8aumxwiZXwedkJ16H_gBkLsKqanlDLfeFqM8,14803
250
250
  web3/providers/eth_tester/main.py,sha256=mI7XAqp0_lZVtVhr7HAh8noJfcxYL9qFfmxoV2jKVPo,5845
251
251
  web3/providers/eth_tester/middleware.py,sha256=LN3UZ789e5pwfBBrx9_1N2ByiEYIy6ioMpYddv1u1Zw,13944
252
252
  web3/providers/websocket/__init__.py,sha256=W5xi6NxUVaskom7k03vd2HCXSH8hXAob2ry-ULiNSUo,232
253
- web3/providers/websocket/request_processor.py,sha256=dlYerMlb3aA2wQ5kN2TlDyJrIsLv4MoqOU47IQtCCeU,10734
253
+ web3/providers/websocket/request_processor.py,sha256=kir6bkAWy6CQdBpNrk_8CB8GPsjXM42SXx7IYlAngqE,11653
254
254
  web3/providers/websocket/websocket.py,sha256=-U2-CGtqpysxZoFHsa-rBeZKjSRejqQSeb5Z12SzKwk,3929
255
255
  web3/providers/websocket/websocket_connection.py,sha256=_W3i_nF9NNRdSwFGwLsDCNXrrhlhV-NvmywX8vbuWvY,1104
256
- web3/providers/websocket/websocket_v2.py,sha256=X_jxeF0QF9gFGP8LZM5_dA2n-6e7WIb6w-i_fOb9lcg,8698
256
+ web3/providers/websocket/websocket_v2.py,sha256=HX-p1CATh2eA02H0vbKh33XQdahoiSp5RH8uUoXzndY,4402
257
257
  web3/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
258
258
  web3/scripts/release/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
259
259
  web3/scripts/release/test_package.py,sha256=DH0AryllcF4zfpWSd0NLPSQGHNoC-Qng5WYYbS5_4c8,1534
@@ -265,7 +265,7 @@ web3/tools/benchmark/reporting.py,sha256=t6XZhitwMcKjIXU6tlPEjgDmozvCSK3RoOW-0bO
265
265
  web3/tools/benchmark/utils.py,sha256=GjSofFEq3ugFtpyBlAx7n6cgZrQ5Xu4-hN_36bQBwnA,1722
266
266
  web3/tools/pytest_ethereum/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
267
267
  web3/tools/pytest_ethereum/_utils.py,sha256=2rZz6L4lXmpTyXFiXWFu8AI2qX4sftzjlbdtqmaWgGE,4158
268
- web3/tools/pytest_ethereum/deployer.py,sha256=QZVWQpbRlHZuMqx8R7ZJIOaAU7-UyCgLBz6KPUAjsZI,1423
268
+ web3/tools/pytest_ethereum/deployer.py,sha256=xAlBX7Mvn6csumjrCItDf8iPLfLwj2OsuAshPdnRPZI,1415
269
269
  web3/tools/pytest_ethereum/exceptions.py,sha256=5H8abL5ywZlSR0ASCR_2klPUDKjncf-7BTVgAcFraUU,380
270
270
  web3/tools/pytest_ethereum/linker.py,sha256=fnkHsX2Yhus29nnPj0bTCkWdzTUeSfvxYIamM9QcqI8,3927
271
271
  web3/tools/pytest_ethereum/plugins.py,sha256=QgC4Lm-pHIAj5IMFcmKyuWa13_mfedkSVmjuE_8Tdzc,645
@@ -275,9 +275,9 @@ web3/utils/address.py,sha256=KC_IpEbixSCuMhaW6V2QCyyJTYKYGS9c8QtI9_aH7zQ,967
275
275
  web3/utils/async_exception_handling.py,sha256=gfLuzP7Y5rc21jZVjWEYAOZUMJkJd9CmsL297UKReow,3096
276
276
  web3/utils/caching.py,sha256=PgfuXiVgPYQuS0S89-jkNOJ3L2uTRt2MkVBvzMkaAXI,1770
277
277
  web3/utils/exception_handling.py,sha256=12xkzIqMAOx0Jcm6PYL98PmWlLPKFll0p9YoLGS_ZNg,3052
278
- web3-6.18.0.dist-info/LICENSE,sha256=ulnXiEqqFp9VyWe8yMFdtDi70RMBJk3mpY3FKujv6l8,1090
279
- web3-6.18.0.dist-info/METADATA,sha256=grPGPcFqgL_8ihZCBlqeP_FL4rwoCPOBTHgSE_R2dqQ,4522
280
- web3-6.18.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
281
- web3-6.18.0.dist-info/entry_points.txt,sha256=2qjzGxFUlYBzoP68fcB3AJyMRunWI70uBoxNp17Brb0,64
282
- web3-6.18.0.dist-info/top_level.txt,sha256=5lRZg30BFUrz8eUK60C7OAjNT3FI4YsGmA-vZ0WIOik,15
283
- web3-6.18.0.dist-info/RECORD,,
278
+ web3-6.19.0.dist-info/LICENSE,sha256=ulnXiEqqFp9VyWe8yMFdtDi70RMBJk3mpY3FKujv6l8,1090
279
+ web3-6.19.0.dist-info/METADATA,sha256=x0ZZ5THuZWBU5i5JndaNJpnoYMemRUafzsdYa5bVOaA,4522
280
+ web3-6.19.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
281
+ web3-6.19.0.dist-info/entry_points.txt,sha256=2qjzGxFUlYBzoP68fcB3AJyMRunWI70uBoxNp17Brb0,64
282
+ web3-6.19.0.dist-info/top_level.txt,sha256=5lRZg30BFUrz8eUK60C7OAjNT3FI4YsGmA-vZ0WIOik,15
283
+ web3-6.19.0.dist-info/RECORD,,
File without changes
File without changes