web3 7.0.0b9__py3-none-any.whl → 7.1.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.
@@ -26,6 +26,9 @@ GET_BLINDED_BLOCKS = "/eth/v1/beacon/blinded_blocks/{0}"
26
26
  # rewards
27
27
  GET_REWARDS = "/eth/v1/beacon/rewards/blocks/{0}"
28
28
 
29
+ # blobs
30
+ GET_BLOB_SIDECARS = "/eth/v1/beacon/blob_sidecars/{0}"
31
+
29
32
  # light client
30
33
  GET_LIGHT_CLIENT_BOOTSTRAP_STRUCTURE = "/eth/v1/beacon/light_client/bootstrap/{0}"
31
34
  GET_LIGHT_CLIENT_UPDATES = "/eth/v1/beacon/light_client/updates"
@@ -1,6 +1,8 @@
1
1
  from typing import (
2
2
  Any,
3
3
  Dict,
4
+ List,
5
+ Optional,
4
6
  )
5
7
 
6
8
  from eth_typing import (
@@ -17,6 +19,7 @@ from web3.beacon.api_endpoints import (
17
19
  GET_BEACON_HEADS,
18
20
  GET_BEACON_STATE,
19
21
  GET_BLINDED_BLOCKS,
22
+ GET_BLOB_SIDECARS,
20
23
  GET_BLOCK,
21
24
  GET_BLOCK_ATTESTATIONS,
22
25
  GET_BLOCK_HEADER,
@@ -64,10 +67,12 @@ class AsyncBeacon:
64
67
  self.request_timeout = request_timeout
65
68
  self._request_session_manager = HTTPSessionManager()
66
69
 
67
- async def _async_make_get_request(self, endpoint_uri: str) -> Dict[str, Any]:
70
+ async def _async_make_get_request(
71
+ self, endpoint_uri: str, params: Optional[Dict[str, str]] = None
72
+ ) -> Dict[str, Any]:
68
73
  uri = URI(self.base_url + endpoint_uri)
69
74
  return await self._request_session_manager.async_json_make_get_request(
70
- uri, timeout=self.request_timeout
75
+ uri, params=params, timeout=self.request_timeout
71
76
  )
72
77
 
73
78
  # [ BEACON endpoints ]
@@ -220,3 +225,14 @@ class AsyncBeacon:
220
225
 
221
226
  async def get_syncing(self) -> Dict[str, Any]:
222
227
  return await self._async_make_get_request(GET_SYNCING)
228
+
229
+ # [ BLOB endpoints ]
230
+
231
+ async def get_blob_sidecars(
232
+ self, block_id: str, indices: Optional[List[int]] = None
233
+ ) -> Dict[str, Any]:
234
+ indices_param = {"indices": ",".join(map(str, indices))} if indices else None
235
+ return await self._async_make_get_request(
236
+ GET_BLOB_SIDECARS.format(block_id),
237
+ params=indices_param,
238
+ )
web3/beacon/beacon.py CHANGED
@@ -1,6 +1,8 @@
1
1
  from typing import (
2
2
  Any,
3
3
  Dict,
4
+ List,
5
+ Optional,
4
6
  )
5
7
 
6
8
  from eth_typing import (
@@ -17,6 +19,7 @@ from web3.beacon.api_endpoints import (
17
19
  GET_BEACON_HEADS,
18
20
  GET_BEACON_STATE,
19
21
  GET_BLINDED_BLOCKS,
22
+ GET_BLOB_SIDECARS,
20
23
  GET_BLOCK,
21
24
  GET_BLOCK_ATTESTATIONS,
22
25
  GET_BLOCK_HEADER,
@@ -62,10 +65,12 @@ class Beacon:
62
65
  self.request_timeout = request_timeout
63
66
  self._request_session_manager = HTTPSessionManager()
64
67
 
65
- def _make_get_request(self, endpoint_url: str) -> Dict[str, Any]:
68
+ def _make_get_request(
69
+ self, endpoint_url: str, params: Optional[Dict[str, str]] = None
70
+ ) -> Dict[str, Any]:
66
71
  uri = URI(self.base_url + endpoint_url)
67
72
  return self._request_session_manager.json_make_get_request(
68
- uri, timeout=self.request_timeout
73
+ uri, params=params, timeout=self.request_timeout
69
74
  )
70
75
 
71
76
  # [ BEACON endpoints ]
@@ -206,3 +211,14 @@ class Beacon:
206
211
 
207
212
  def get_syncing(self) -> Dict[str, Any]:
208
213
  return self._make_get_request(GET_SYNCING)
214
+
215
+ # [ BLOB endpoints ]
216
+
217
+ def get_blob_sidecars(
218
+ self, block_id: str, indices: Optional[List[int]] = None
219
+ ) -> Dict[str, Any]:
220
+ indices_param = {"indices": ",".join(map(str, indices))} if indices else None
221
+ return self._make_get_request(
222
+ GET_BLOB_SIDECARS.format(block_id),
223
+ params=indices_param,
224
+ )
@@ -319,8 +319,8 @@ class AsyncContractFunction(BaseContractFunction):
319
319
  state_override,
320
320
  ccip_read_enabled,
321
321
  self.decode_tuples,
322
- *self.args,
323
- **self.kwargs,
322
+ *self.args or (),
323
+ **self.kwargs or {},
324
324
  )
325
325
 
326
326
  async def transact(self, transaction: Optional[TxParams] = None) -> HexBytes:
@@ -332,8 +332,8 @@ class AsyncContractFunction(BaseContractFunction):
332
332
  setup_transaction,
333
333
  self.contract_abi,
334
334
  self.abi,
335
- *self.args,
336
- **self.kwargs,
335
+ *self.args or (),
336
+ **self.kwargs or {},
337
337
  )
338
338
 
339
339
  async def estimate_gas(
@@ -352,8 +352,8 @@ class AsyncContractFunction(BaseContractFunction):
352
352
  self.abi,
353
353
  block_identifier,
354
354
  state_override,
355
- *self.args,
356
- **self.kwargs,
355
+ *self.args or (),
356
+ **self.kwargs or {},
357
357
  )
358
358
 
359
359
  async def build_transaction(
@@ -367,8 +367,8 @@ class AsyncContractFunction(BaseContractFunction):
367
367
  built_transaction,
368
368
  self.contract_abi,
369
369
  self.abi,
370
- *self.args,
371
- **self.kwargs,
370
+ *self.args or (),
371
+ **self.kwargs or {},
372
372
  )
373
373
 
374
374
  @staticmethod
web3/contract/contract.py CHANGED
@@ -318,12 +318,13 @@ class ContractFunction(BaseContractFunction):
318
318
  state_override,
319
319
  ccip_read_enabled,
320
320
  self.decode_tuples,
321
- *self.args,
322
- **self.kwargs,
321
+ *self.args or (),
322
+ **self.kwargs or {},
323
323
  )
324
324
 
325
325
  def transact(self, transaction: Optional[TxParams] = None) -> HexBytes:
326
326
  setup_transaction = self._transact(transaction)
327
+
327
328
  return transact_with_contract_function(
328
329
  self.address,
329
330
  self.w3,
@@ -331,8 +332,8 @@ class ContractFunction(BaseContractFunction):
331
332
  setup_transaction,
332
333
  self.contract_abi,
333
334
  self.abi,
334
- *self.args,
335
- **self.kwargs,
335
+ *self.args or (),
336
+ **self.kwargs or {},
336
337
  )
337
338
 
338
339
  def estimate_gas(
@@ -351,12 +352,13 @@ class ContractFunction(BaseContractFunction):
351
352
  self.abi,
352
353
  block_identifier,
353
354
  state_override,
354
- *self.args,
355
- **self.kwargs,
355
+ *self.args or (),
356
+ **self.kwargs or {},
356
357
  )
357
358
 
358
359
  def build_transaction(self, transaction: Optional[TxParams] = None) -> TxParams:
359
360
  built_transaction = self._build_transaction(transaction)
361
+
360
362
  return build_transaction_for_function(
361
363
  self.address,
362
364
  self.w3,
@@ -364,8 +366,8 @@ class ContractFunction(BaseContractFunction):
364
366
  built_transaction,
365
367
  self.contract_abi,
366
368
  self.abi,
367
- *self.args,
368
- **self.kwargs,
369
+ *self.args or (),
370
+ **self.kwargs or {},
369
371
  )
370
372
 
371
373
  @staticmethod
web3/datastructures.py CHANGED
@@ -182,7 +182,7 @@ class NamedElementOnion(Mapping[TKey, TValue]):
182
182
  if name is None:
183
183
  name = cast(TKey, element)
184
184
 
185
- name = self._repr_if_not_hashable(name)
185
+ name = self._build_name(name)
186
186
 
187
187
  if name in self._queue:
188
188
  if name is element:
@@ -219,7 +219,7 @@ class NamedElementOnion(Mapping[TKey, TValue]):
219
219
  if name is None:
220
220
  name = cast(TKey, element)
221
221
 
222
- name = self._repr_if_not_hashable(name)
222
+ name = self._build_name(name)
223
223
 
224
224
  self._queue.move_to_end(name, last=False)
225
225
  elif layer == len(self._queue):
@@ -233,7 +233,7 @@ class NamedElementOnion(Mapping[TKey, TValue]):
233
233
  self._queue.clear()
234
234
 
235
235
  def replace(self, old: TKey, new: TKey) -> TValue:
236
- old_name = self._repr_if_not_hashable(old)
236
+ old_name = self._build_name(old)
237
237
 
238
238
  if old_name not in self._queue:
239
239
  raise Web3ValueError(
@@ -248,15 +248,25 @@ class NamedElementOnion(Mapping[TKey, TValue]):
248
248
  self._queue[old_name] = new
249
249
  return to_be_replaced
250
250
 
251
- def _repr_if_not_hashable(self, value: TKey) -> TKey:
251
+ @staticmethod
252
+ def _build_name(value: TKey) -> TKey:
252
253
  try:
253
254
  value.__hash__()
255
+ return value
254
256
  except TypeError:
255
- value = cast(TKey, repr(value))
256
- return value
257
+ # unhashable, unnamed elements
258
+ if not callable(value):
259
+ raise Web3TypeError(
260
+ f"Expected a callable or hashable type, got {type(value)}"
261
+ )
262
+ # This will either be ``Web3Middleware`` class or the ``build`` method of a
263
+ # ``Web3MiddlewareBuilder``. Instantiate with empty ``Web3`` and use a
264
+ # unique identifier with the ``__hash__()`` as the name.
265
+ v = value(None)
266
+ return cast(TKey, f"{v.__class__}<{v.__hash__()}>")
257
267
 
258
268
  def remove(self, old: TKey) -> None:
259
- old_name = self._repr_if_not_hashable(old)
269
+ old_name = self._build_name(old)
260
270
  if old_name not in self._queue:
261
271
  raise Web3ValueError("You can only remove something that has been added")
262
272
  del self._queue[old_name]
@@ -270,8 +280,8 @@ class NamedElementOnion(Mapping[TKey, TValue]):
270
280
  return [(val, key) for key, val in reversed(self._queue.items())]
271
281
 
272
282
  def _replace_with_new_name(self, old: TKey, new: TKey) -> None:
273
- old_name = self._repr_if_not_hashable(old)
274
- new_name = self._repr_if_not_hashable(new)
283
+ old_name = self._build_name(old)
284
+ new_name = self._build_name(new)
275
285
 
276
286
  self._queue[new_name] = new
277
287
  found_old = False
@@ -293,11 +303,11 @@ class NamedElementOnion(Mapping[TKey, TValue]):
293
303
  return NamedElementOnion(cast(List[Any], combined.items()))
294
304
 
295
305
  def __contains__(self, element: Any) -> bool:
296
- element_name = self._repr_if_not_hashable(element)
306
+ element_name = self._build_name(element)
297
307
  return element_name in self._queue
298
308
 
299
309
  def __getitem__(self, element: TKey) -> TValue:
300
- element_name = self._repr_if_not_hashable(element)
310
+ element_name = self._build_name(element)
301
311
  return self._queue[element_name]
302
312
 
303
313
  def __len__(self) -> int:
web3/middleware/base.py CHANGED
@@ -40,6 +40,14 @@ class Web3Middleware:
40
40
  def __init__(self, w3: Union["AsyncWeb3", "Web3"]) -> None:
41
41
  self._w3 = w3
42
42
 
43
+ def __hash__(self) -> int:
44
+ return hash(f"{self.__class__.__name__}({str(self.__dict__)})")
45
+
46
+ def __eq__(self, other: Any) -> bool:
47
+ if not isinstance(other, Web3Middleware):
48
+ return False
49
+ return self.__hash__() == other.__hash__()
50
+
43
51
  # -- sync -- #
44
52
 
45
53
  def wrap_make_request(self, make_request: "MakeRequestFn") -> "MakeRequestFn":
@@ -0,0 +1,33 @@
1
+ """
2
+ The goal of this script is to install the latest versions, including pre-releases, for
3
+ libraries that we maintain (and therefore control the release process) during our CI
4
+ runs. This helps us test pre-releases before they cause any issues once stable versions
5
+ are released.
6
+ """
7
+
8
+ import subprocess
9
+ import sys
10
+
11
+ ETHEREUM_LIBRARIES = [
12
+ "eth-account",
13
+ "eth-abi",
14
+ "eth-account",
15
+ "eth-hash[pycryptodome]",
16
+ "eth-typing",
17
+ "eth-utils",
18
+ "hexbytes",
19
+ "eth-tester[py-evm]",
20
+ "py-geth",
21
+ ]
22
+
23
+
24
+ def install_eth_pre_releases() -> None:
25
+ for lib in ETHEREUM_LIBRARIES:
26
+ print(f"Installing {lib} with `--pre` and `-U`")
27
+ subprocess.check_call(
28
+ [sys.executable, "-m", "pip", "install", "--pre", "-U", lib]
29
+ )
30
+
31
+
32
+ if __name__ == "__main__":
33
+ install_eth_pre_releases()
@@ -0,0 +1,16 @@
1
+ import re
2
+
3
+
4
+ def get_pygeth_version() -> str:
5
+ with open("setup.py") as f:
6
+ setup_contents = f.read()
7
+ version_match = re.search(r"py-geth\s*([><=~!]+)\s*([\d.]+)", setup_contents)
8
+ if version_match:
9
+ return "".join(version_match.group(1, 2))
10
+ else:
11
+ raise ValueError("py-geth not found in setup.py")
12
+
13
+
14
+ if __name__ == "__main__":
15
+ version = get_pygeth_version()
16
+ print(version)
File without changes
@@ -0,0 +1,190 @@
1
+ import argparse
2
+ import asyncio
3
+ from collections import (
4
+ defaultdict,
5
+ )
6
+ import logging
7
+ import sys
8
+ import timeit
9
+ from typing import (
10
+ Any,
11
+ Callable,
12
+ Dict,
13
+ Union,
14
+ )
15
+
16
+ from web3 import (
17
+ AsyncHTTPProvider,
18
+ AsyncWeb3,
19
+ HTTPProvider,
20
+ Web3,
21
+ )
22
+ from web3.middleware import (
23
+ BufferedGasEstimateMiddleware,
24
+ GasPriceStrategyMiddleware,
25
+ )
26
+ from web3.tools.benchmark.node import (
27
+ GethBenchmarkFixture,
28
+ )
29
+ from web3.tools.benchmark.reporting import (
30
+ print_entry,
31
+ print_footer,
32
+ print_header,
33
+ )
34
+ from web3.tools.benchmark.utils import (
35
+ wait_for_aiohttp,
36
+ wait_for_http,
37
+ )
38
+ from web3.types import (
39
+ Wei,
40
+ )
41
+
42
+ KEYFILE_PW = "web3py-test"
43
+
44
+ parser = argparse.ArgumentParser()
45
+ parser.add_argument(
46
+ "--num-calls",
47
+ type=int,
48
+ default=10,
49
+ help="The number of RPC calls to make",
50
+ )
51
+
52
+ # TODO - layers to test:
53
+ # contract.functions.method(...).call()
54
+ # w3.eth.call(...)
55
+ # HTTPProvider.make_request(...)
56
+
57
+
58
+ def build_web3_http(endpoint_uri: str) -> Web3:
59
+ wait_for_http(endpoint_uri)
60
+ _w3 = Web3(
61
+ HTTPProvider(endpoint_uri),
62
+ middleware=[GasPriceStrategyMiddleware, BufferedGasEstimateMiddleware],
63
+ )
64
+ return _w3
65
+
66
+
67
+ async def build_async_w3_http(endpoint_uri: str) -> AsyncWeb3:
68
+ await wait_for_aiohttp(endpoint_uri)
69
+ _w3 = AsyncWeb3(
70
+ AsyncHTTPProvider(endpoint_uri),
71
+ middleware=[GasPriceStrategyMiddleware, BufferedGasEstimateMiddleware],
72
+ )
73
+ return _w3
74
+
75
+
76
+ def sync_benchmark(func: Callable[..., Any], n: int) -> Union[float, str]:
77
+ try:
78
+ starttime = timeit.default_timer()
79
+ for _ in range(n):
80
+ func()
81
+ endtime = timeit.default_timer()
82
+ execution_time = endtime - starttime
83
+ return execution_time
84
+ except Exception:
85
+ return "N/A"
86
+
87
+
88
+ async def async_benchmark(func: Callable[..., Any], n: int) -> Union[float, str]:
89
+ try:
90
+ starttime = timeit.default_timer()
91
+ for result in asyncio.as_completed([func() for _ in range(n)]):
92
+ await result
93
+ execution_time = timeit.default_timer() - starttime
94
+ return execution_time
95
+ except Exception:
96
+ return "N/A"
97
+
98
+
99
+ def main(logger: logging.Logger, num_calls: int) -> None:
100
+ fixture = GethBenchmarkFixture()
101
+ for built_fixture in fixture.build():
102
+ for _ in built_fixture:
103
+ w3_http = build_web3_http(fixture.endpoint_uri)
104
+ try:
105
+ loop = asyncio.get_running_loop()
106
+ except RuntimeError:
107
+ loop = asyncio.new_event_loop()
108
+ asyncio.set_event_loop(loop)
109
+
110
+ # -- sync -- #
111
+ account = w3_http.eth.accounts[0]
112
+
113
+ # -- async -- #
114
+ async_w3_http = loop.run_until_complete(
115
+ build_async_w3_http(fixture.endpoint_uri)
116
+ )
117
+ async_accounts = loop.run_until_complete(async_w3_http.eth.accounts)
118
+ async_account = async_accounts[0]
119
+
120
+ methods = [
121
+ {
122
+ "name": "eth_gasPrice",
123
+ "params": {},
124
+ "exec": lambda w3_http=w3_http: w3_http.eth.gas_price,
125
+ "async_exec": lambda async_w3_http=async_w3_http: async_w3_http.eth.gas_price, # noqa: E501
126
+ },
127
+ {
128
+ "name": "eth_sendTransaction",
129
+ "params": {},
130
+ "exec": lambda w3_http=w3_http, account=account: w3_http.eth.send_transaction( # noqa: E501
131
+ {
132
+ "to": "0xd3CdA913deB6f67967B99D67aCDFa1712C293601",
133
+ "from": account,
134
+ "value": Wei(1),
135
+ }
136
+ ),
137
+ "async_exec": lambda async_w3_http=async_w3_http, async_account=async_account: async_w3_http.eth.send_transaction( # noqa: E501
138
+ {
139
+ "to": "0xd3CdA913deB6f67967B99D67aCDFa1712C293601",
140
+ "from": async_account,
141
+ "value": Wei(1),
142
+ }
143
+ ),
144
+ },
145
+ {
146
+ "name": "eth_blockNumber",
147
+ "params": {},
148
+ "exec": lambda w3_http=w3_http: w3_http.eth.block_number,
149
+ "async_exec": lambda async_w3_http=async_w3_http: async_w3_http.eth.block_number, # noqa: E501
150
+ },
151
+ {
152
+ "name": "eth_getBlock",
153
+ "params": {},
154
+ "exec": lambda w3_http=w3_http: w3_http.eth.get_block(1),
155
+ "async_exec": lambda async_w3_http=async_w3_http: async_w3_http.eth.get_block( # noqa: E501
156
+ 1
157
+ ),
158
+ },
159
+ ]
160
+
161
+ def benchmark(
162
+ method: Dict[str, Any], loop: asyncio.AbstractEventLoop = loop
163
+ ) -> None:
164
+ outcomes: Dict[str, Union[str, float]] = defaultdict(lambda: "N/A")
165
+ outcomes["name"] = method["name"]
166
+ outcomes["HTTPProvider"] = sync_benchmark(
167
+ method["exec"],
168
+ num_calls,
169
+ )
170
+ outcomes["AsyncHTTPProvider"] = loop.run_until_complete(
171
+ async_benchmark(method["async_exec"], num_calls)
172
+ )
173
+ print_entry(logger, outcomes)
174
+
175
+ print_header(logger, num_calls)
176
+
177
+ for method in methods:
178
+ benchmark(method)
179
+
180
+ print_footer(logger)
181
+
182
+
183
+ if __name__ == "__main__":
184
+ args = parser.parse_args()
185
+
186
+ logger = logging.getLogger()
187
+ logger.setLevel(logging.INFO)
188
+ logger.addHandler(logging.StreamHandler(sys.stdout))
189
+
190
+ main(logger, args.num_calls)
@@ -0,0 +1,120 @@
1
+ import os
2
+ import socket
3
+ from subprocess import (
4
+ PIPE,
5
+ Popen,
6
+ check_output,
7
+ )
8
+ from tempfile import (
9
+ TemporaryDirectory,
10
+ )
11
+ from typing import (
12
+ Any,
13
+ Generator,
14
+ Sequence,
15
+ )
16
+ import zipfile
17
+
18
+ from geth.install import (
19
+ get_executable_path,
20
+ install_geth,
21
+ )
22
+
23
+ from web3.tools.benchmark.utils import (
24
+ kill_proc_gracefully,
25
+ )
26
+
27
+ GETH_FIXTURE_ZIP = "geth-1.14.5-fixture.zip"
28
+
29
+
30
+ class GethBenchmarkFixture:
31
+ def __init__(self) -> None:
32
+ self.rpc_port = self._rpc_port()
33
+ self.endpoint_uri = self._endpoint_uri()
34
+ self.geth_binary = self._geth_binary()
35
+
36
+ def build(self) -> Generator[Any, None, None]:
37
+ with TemporaryDirectory() as base_dir:
38
+ zipfile_path = os.path.abspath(
39
+ os.path.join(
40
+ os.path.dirname(__file__),
41
+ "../../../tests/integration/",
42
+ GETH_FIXTURE_ZIP,
43
+ )
44
+ )
45
+ tmp_datadir = os.path.join(str(base_dir), "datadir")
46
+ with zipfile.ZipFile(zipfile_path, "r") as zip_ref:
47
+ zip_ref.extractall(tmp_datadir)
48
+ self.datadir = tmp_datadir
49
+
50
+ genesis_file = os.path.join(self.datadir, "genesis.json")
51
+
52
+ yield self._geth_process(self.datadir, genesis_file, self.rpc_port)
53
+
54
+ def _rpc_port(self) -> str:
55
+ sock = socket.socket()
56
+ sock.bind(("127.0.0.1", 0))
57
+ port = sock.getsockname()[1]
58
+ sock.close()
59
+ return str(port)
60
+
61
+ def _endpoint_uri(self) -> str:
62
+ return f"http://localhost:{self.rpc_port}"
63
+
64
+ def _geth_binary(self) -> str:
65
+ if "GETH_BINARY" in os.environ:
66
+ return os.environ["GETH_BINARY"]
67
+ elif "GETH_VERSION" in os.environ:
68
+ geth_version = os.environ["GETH_VERSION"]
69
+ _geth_binary = get_executable_path(geth_version)
70
+ if not os.path.exists(_geth_binary):
71
+ install_geth(geth_version)
72
+ assert os.path.exists(_geth_binary)
73
+ return _geth_binary
74
+ else:
75
+ return "geth"
76
+
77
+ def _geth_command_arguments(self, datadir: str) -> Sequence[str]:
78
+ return (
79
+ self.geth_binary,
80
+ "--dev",
81
+ "--dev.period",
82
+ "100",
83
+ "--datadir",
84
+ datadir,
85
+ "--nodiscover",
86
+ "--http",
87
+ "--http.port",
88
+ self.rpc_port,
89
+ "--http.api",
90
+ "admin,eth,net,web3",
91
+ "--ipcdisable",
92
+ "--password",
93
+ os.path.join(datadir, "keystore", "pw.txt"),
94
+ )
95
+
96
+ def _geth_process(
97
+ self, datadir: str, genesis_file: str, rpc_port: str
98
+ ) -> Generator[Any, None, None]:
99
+ init_datadir_command = (
100
+ self.geth_binary,
101
+ "--datadir",
102
+ str(datadir),
103
+ "init",
104
+ str(genesis_file),
105
+ )
106
+ check_output(
107
+ init_datadir_command,
108
+ stdin=PIPE,
109
+ stderr=PIPE,
110
+ )
111
+ proc = Popen(
112
+ self._geth_command_arguments(datadir),
113
+ stdin=PIPE,
114
+ stdout=PIPE,
115
+ stderr=PIPE,
116
+ )
117
+ try:
118
+ yield proc
119
+ finally:
120
+ kill_proc_gracefully(proc)
@@ -0,0 +1,39 @@
1
+ from logging import (
2
+ Logger,
3
+ )
4
+ from typing import (
5
+ Any,
6
+ Dict,
7
+ )
8
+
9
+
10
+ def print_header(logger: Logger, num_calls: int) -> None:
11
+ logger.info(
12
+ "|{:^26}|{:^20}|{:^20}|{:^20}|{:^20}|".format(
13
+ f"Method ({num_calls} calls)",
14
+ "HTTPProvider",
15
+ "AsyncHTTProvider",
16
+ "IPCProvider",
17
+ "WebSocketProvider",
18
+ )
19
+ )
20
+ logger.info("-" * 112)
21
+
22
+
23
+ def print_entry(
24
+ logger: Logger,
25
+ method_benchmarks: Dict[str, Any],
26
+ ) -> None:
27
+ logger.info(
28
+ "|{:^26}|{:^20.10}|{:^20.10}|{:^20.10}|{:^20.10}|".format(
29
+ method_benchmarks["name"],
30
+ method_benchmarks["HTTPProvider"],
31
+ method_benchmarks["AsyncHTTPProvider"],
32
+ method_benchmarks["IPCProvider"],
33
+ method_benchmarks["WebSocketProvider"],
34
+ )
35
+ )
36
+
37
+
38
+ def print_footer(logger: Logger) -> None:
39
+ logger.info("-" * 112)
@@ -0,0 +1,69 @@
1
+ import asyncio
2
+ import signal
3
+ import socket
4
+ import time
5
+ from typing import (
6
+ Any,
7
+ )
8
+
9
+ import aiohttp
10
+ import requests
11
+
12
+
13
+ def wait_for_socket(ipc_path: str, timeout: int = 30) -> None:
14
+ start = time.time()
15
+ while time.time() < start + timeout:
16
+ try:
17
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
18
+ sock.connect(ipc_path)
19
+ sock.settimeout(timeout)
20
+ except OSError:
21
+ time.sleep(0.01)
22
+ else:
23
+ break
24
+
25
+
26
+ def wait_for_http(endpoint_uri: str, timeout: int = 60) -> None:
27
+ start = time.time()
28
+ while time.time() < start + timeout:
29
+ try:
30
+ requests.get(endpoint_uri)
31
+ except requests.ConnectionError:
32
+ time.sleep(0.01)
33
+ else:
34
+ break
35
+
36
+
37
+ async def wait_for_aiohttp(endpoint_uri: str, timeout: int = 60) -> None:
38
+ start = time.time()
39
+ while time.time() < start + timeout:
40
+ try:
41
+ async with aiohttp.ClientSession() as session:
42
+ await session.get(endpoint_uri)
43
+ except aiohttp.client_exceptions.ClientConnectorError:
44
+ await asyncio.sleep(0.01)
45
+ else:
46
+ break
47
+
48
+
49
+ def wait_for_popen(proc: Any, timeout: int) -> None:
50
+ start = time.time()
51
+ while time.time() < start + timeout:
52
+ if proc.poll() is None:
53
+ time.sleep(0.01)
54
+ else:
55
+ break
56
+
57
+
58
+ def kill_proc_gracefully(proc: Any) -> None:
59
+ if proc.poll() is None:
60
+ proc.send_signal(signal.SIGINT)
61
+ wait_for_popen(proc, 13)
62
+
63
+ if proc.poll() is None:
64
+ proc.terminate()
65
+ wait_for_popen(proc, 5)
66
+
67
+ if proc.poll() is None:
68
+ proc.kill()
69
+ wait_for_popen(proc, 2)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: web3
3
- Version: 7.0.0b9
3
+ Version: 7.1.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
@@ -20,13 +20,13 @@ Classifier: Programming Language :: Python :: 3.12
20
20
  Requires-Python: >=3.8, <4
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: aiohttp >=3.7.4.post0
24
23
  Requires-Dist: eth-abi >=5.0.1
25
24
  Requires-Dist: eth-account >=0.13.1
26
25
  Requires-Dist: eth-hash[pycryptodome] >=0.5.1
27
- Requires-Dist: eth-typing >=5.0.0b3
28
- Requires-Dist: eth-utils >=5.0.0b1
26
+ Requires-Dist: eth-typing >=5.0.0
27
+ Requires-Dist: eth-utils >=5.0.0
29
28
  Requires-Dist: hexbytes >=1.2.0
29
+ Requires-Dist: aiohttp >=3.7.4.post0
30
30
  Requires-Dist: pydantic >=2.4.0
31
31
  Requires-Dist: requests >=2.23.0
32
32
  Requires-Dist: typing-extensions >=4.0.1
@@ -53,9 +53,8 @@ Requires-Dist: sphinx >=6.0.0 ; extra == 'dev'
53
53
  Requires-Dist: sphinx-autobuild >=2021.3.14 ; extra == 'dev'
54
54
  Requires-Dist: sphinx-rtd-theme >=1.0.0 ; extra == 'dev'
55
55
  Requires-Dist: towncrier <22,>=21 ; extra == 'dev'
56
- Requires-Dist: eth-account >=0.13.0 ; extra == 'dev'
57
56
  Requires-Dist: eth-tester[py-evm] <0.13.0b1,>=0.11.0b1 ; extra == 'dev'
58
- Requires-Dist: py-geth >=5.0.0b1 ; extra == 'dev'
57
+ Requires-Dist: py-geth >=5.0.0 ; extra == 'dev'
59
58
  Requires-Dist: pytest-asyncio <0.23,>=0.18.1 ; extra == 'dev'
60
59
  Requires-Dist: pytest-xdist >=2.4.0 ; extra == 'dev'
61
60
  Requires-Dist: pytest >=7.0.0 ; extra == 'dev'
@@ -64,10 +63,9 @@ Requires-Dist: sphinx >=6.0.0 ; extra == 'docs'
64
63
  Requires-Dist: sphinx-autobuild >=2021.3.14 ; extra == 'docs'
65
64
  Requires-Dist: sphinx-rtd-theme >=1.0.0 ; extra == 'docs'
66
65
  Requires-Dist: towncrier <22,>=21 ; extra == 'docs'
67
- Requires-Dist: eth-account >=0.13.0 ; extra == 'docs'
68
66
  Provides-Extra: test
69
67
  Requires-Dist: eth-tester[py-evm] <0.13.0b1,>=0.11.0b1 ; extra == 'test'
70
- Requires-Dist: py-geth >=5.0.0b1 ; extra == 'test'
68
+ Requires-Dist: py-geth >=5.0.0 ; extra == 'test'
71
69
  Requires-Dist: pytest-asyncio <0.23,>=0.18.1 ; extra == 'test'
72
70
  Requires-Dist: pytest-mock >=1.10 ; extra == 'test'
73
71
  Requires-Dist: pytest-xdist >=2.4.0 ; extra == 'test'
@@ -13,7 +13,7 @@ ens/specs/nf.json,sha256=kGZcTE_UxTl3WZwMUP6m8KbQQOKdw7PWzmuW7ewQSUs,48403
13
13
  ens/specs/normalization_spec.json,sha256=xn3N9a-6KHMLu3MeCBsmOxSzIzUQykzE9EscKK1a3w8,3115334
14
14
  web3/__init__.py,sha256=P11QAEV_GYoZq9ij8gDzFx5tKzJY2aMXG-keg2Lg1xs,1277
15
15
  web3/constants.py,sha256=eQLRQVMFPbgpOjjkPTMHkY-syncJuO-sPX5UrCSRjzQ,564
16
- web3/datastructures.py,sha256=Yc45cXgoXvhV0HPvnmkFFOEVDtLr-Pftc_f5q-uQY1M,10939
16
+ web3/datastructures.py,sha256=LbUsfE0icgRRTXsC_LATR-LtmO7MAYwYB5D-6LCX1jE,11366
17
17
  web3/exceptions.py,sha256=5Yc-tUdmcnwGv1dxg45iD3Tor3IKMfedA9U_xZ4AR3M,9081
18
18
  web3/geth.py,sha256=IQYeqiVSqcskuXWgDR35UBuVsD-whhvTpDltO4vvCvE,5867
19
19
  web3/logs.py,sha256=ROs-mDMH_ZOecE7hfbWA5yp27G38FbLjX4lO_WtlZxQ,198
@@ -97,13 +97,13 @@ web3/_utils/module_testing/web3_module.py,sha256=7c6penGbHn381fPTYY6DsXKv56xGQpY
97
97
  web3/auto/__init__.py,sha256=ZbzAiCZMdt_tCTTPvH6t8NCVNroKKkt7TSVBBNR74Is,44
98
98
  web3/auto/gethdev.py,sha256=MuWD2gxv0xDv_SzPsp9mSkS1oG4P54xFK83qw9NvswA,438
99
99
  web3/beacon/__init__.py,sha256=Ac6YiNgU8D8Ynnh5RwSCx2NwPyjnpFjpXeHuSssFbaU,113
100
- web3/beacon/api_endpoints.py,sha256=dkekSCmkat5QIfwKzwm49CyVcRb-pIbn1nZHB4F8M0U,2208
101
- web3/beacon/async_beacon.py,sha256=5PErS2VjhNj-GPg3WKxxJv02ZZWyu3m46sWjGMpi33A,7602
102
- web3/beacon/beacon.py,sha256=NT4ebD53uesPj8I0CpqkBJ_U-o2_QFLRVM7tNnlVY0Q,6758
100
+ web3/beacon/api_endpoints.py,sha256=0mHrYFYAWHfF9OGzrFdg012L_ocU2nGDXUTU1isOo7o,2272
101
+ web3/beacon/async_beacon.py,sha256=9-V-rfPwj-SbksHKSYs2Quk8frE2AJXjH908cbSM8v0,8098
102
+ web3/beacon/beacon.py,sha256=tPA9ABPm6MyzbzutiphkhFzOAxLresmftG5UjWkuNyY,7236
103
103
  web3/contract/__init__.py,sha256=qeZRtTw9xriwoD82w6vePDuPBZ35-CMVdkzViBSH3Qs,293
104
- web3/contract/async_contract.py,sha256=dkYeb4G9qwgSzL6cG0Bzjz915bqVzPCbkViSf0OKAg0,20545
104
+ web3/contract/async_contract.py,sha256=KYB-e1GCTZINTRu0Y1f2IIp4LWg2UvKIRFFSIrsjfUs,20593
105
105
  web3/contract/base_contract.py,sha256=qfYzMC-PlefkAQVGplXwdYi5I37DwEe5Slbp5-oOc6U,38053
106
- web3/contract/contract.py,sha256=BO0Xm6sUo_PxhgUxe6fT1Qh3jR61ZiniTVeZjFGJ05c,20124
106
+ web3/contract/contract.py,sha256=wB5g6H7PoAyp4wN__3GGXMrDCvEYuj6crZL4Q2ipTRE,20174
107
107
  web3/contract/utils.py,sha256=bonHXESnb9xhvMzJoi271qppwpy2D6yaHtUwt56wEJc,17853
108
108
  web3/eth/__init__.py,sha256=qDLxOcHHIzzPD7xzwy6Wcs0lLPQieB7WN0Ax25ctit8,197
109
109
  web3/eth/async_eth.py,sha256=elPH3Atkayk3afwepDRP3ibB7EK8MziK0fPikpKCLxI,23176
@@ -114,7 +114,7 @@ web3/gas_strategies/rpc.py,sha256=3Va-32jdmHkX7tzQCmh17ms2D6te5zZcqHP1326BdpY,35
114
114
  web3/gas_strategies/time_based.py,sha256=oGk6nBUD4iMC8wl1vzf-nhURaqyPWYdPvNU0C3RIs8g,9071
115
115
  web3/middleware/__init__.py,sha256=fSmPCYJOO8Qp5p-Vm_Z4XPJATu2qN7KJRypYNSO6_uM,2830
116
116
  web3/middleware/attrdict.py,sha256=NY5yxlFOfLBBmcIjl8R-uP2dTz9ITIyTttG8-QcJWCI,2259
117
- web3/middleware/base.py,sha256=AFIRLRxoQ63lEdhsRe-sATyHaYdiwNVklPOGc9ivXrA,5103
117
+ web3/middleware/base.py,sha256=aHBUWc5pSohLUZ7zcCgrVqp_H_1PTqh31x2n6vWqzuY,5376
118
118
  web3/middleware/buffered_gas_estimate.py,sha256=EmxUd-uO959UVroPsPKkl7oDa8Tw6N8BQLB6Urng5Eo,1647
119
119
  web3/middleware/filter.py,sha256=I09sSE_q_dhWX5_24KVWhVXZNevwViI7wucJBP4TZl4,22221
120
120
  web3/middleware/formatting.py,sha256=hqe5XQE1n5Fmj6riJp7i3oIoZkd-4ChQc7UK8f3HB6I,7567
@@ -147,16 +147,23 @@ web3/providers/rpc/async_rpc.py,sha256=hibsCoyrAD199ExAEyHRsEnZ0_rDP_2EC2k5g-D2z
147
147
  web3/providers/rpc/rpc.py,sha256=ePlGdlkvQTaf2Wi2khxiY-rRj-OFcPlpDMuTPLKaAyU,5655
148
148
  web3/providers/rpc/utils.py,sha256=_mtoZMMIoZpPA8J8U5DfRxaNQmi8bw0ZVUiqn1Nz4co,2154
149
149
  web3/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
150
+ web3/scripts/install_pre_releases.py,sha256=uVxsZk239640yxiqlPhfXxZKSsh3858pURKppi9kM5U,821
151
+ web3/scripts/parse_pygeth_version.py,sha256=BZjWOsJmYuFbAnFuB1jec9Rl6z0tJJNFFV38sJvDfGo,416
150
152
  web3/scripts/release/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
151
153
  web3/scripts/release/test_package.py,sha256=DH0AryllcF4zfpWSd0NLPSQGHNoC-Qng5WYYbS5_4c8,1534
154
+ web3/tools/benchmark/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
155
+ web3/tools/benchmark/main.py,sha256=9nBC8yvdiNPoRuNlcqKC6HKWly_iwOYSeG0cOQCjfpg,5810
156
+ web3/tools/benchmark/node.py,sha256=n73GckmBKLm4_urC7HfF_Z3ZURffNMjq6ymzb9HM9c8,3252
157
+ web3/tools/benchmark/reporting.py,sha256=G2bj_Eo2kBV06GARDYK9zr0VqesiR0_5JLKvhAo6zRM,912
158
+ web3/tools/benchmark/utils.py,sha256=7OOdUD71AVWi0cowAE9ekMgqlfcJwk3vrNnMCHtiGdU,1696
152
159
  web3/utils/__init__.py,sha256=XwpyVR4EBkfqV5SHBH3maNyNBy624EwqujRgetLc7PU,1781
153
160
  web3/utils/abi.py,sha256=iSBaCW41UxB1q1UHDPwJ1QJbdiuYmTWNu8m6E28DqlY,18672
154
161
  web3/utils/address.py,sha256=KC_IpEbixSCuMhaW6V2QCyyJTYKYGS9c8QtI9_aH7zQ,967
155
162
  web3/utils/async_exception_handling.py,sha256=GZWSBFC0-Wmwz1tpTie-1AKRbIQH7JkmBpf5bXrUTzY,3320
156
163
  web3/utils/caching.py,sha256=IG_IxW-jyiRklrIyUgjOj3GQvcXrok0KLDX3ch_6wuA,2390
157
164
  web3/utils/exception_handling.py,sha256=k31JROfUyKIm9PoEWOtYSkIq9wL8SOBwQfnSLNQyfnM,3097
158
- web3-7.0.0b9.dist-info/LICENSE,sha256=ScEyLx1vWrB0ybKiZKKTXm5QhVksHCEUtTp4lwYV45I,1095
159
- web3-7.0.0b9.dist-info/METADATA,sha256=3h7NWNTTSiFvBC020AhFwyeTuENWivxCmfIrBNz8KzY,5103
160
- web3-7.0.0b9.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
161
- web3-7.0.0b9.dist-info/top_level.txt,sha256=iwupuJh7wgypXrpk_awszyri3TahRr5vxSphNyvt1bU,9
162
- web3-7.0.0b9.dist-info/RECORD,,
165
+ web3-7.1.0.dist-info/LICENSE,sha256=ScEyLx1vWrB0ybKiZKKTXm5QhVksHCEUtTp4lwYV45I,1095
166
+ web3-7.1.0.dist-info/METADATA,sha256=p_1iA6mObqMRYbT9SN-0xI9fr_Wh-AN6-fZcOknn1BU,4986
167
+ web3-7.1.0.dist-info/WHEEL,sha256=UvcQYKBHoFqaQd6LKyqHw9fxEolWLQnlzP0h_LgJAfI,91
168
+ web3-7.1.0.dist-info/top_level.txt,sha256=iwupuJh7wgypXrpk_awszyri3TahRr5vxSphNyvt1bU,9
169
+ web3-7.1.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (72.1.0)
2
+ Generator: setuptools (74.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
File without changes