py-geth 4.2.0__py3-none-any.whl → 5.2.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.
- geth/__init__.py +12 -2
- geth/accounts.py +87 -36
- geth/chain.py +68 -83
- geth/exceptions.py +86 -13
- geth/genesis.json +25 -8
- geth/install.py +126 -132
- geth/main.py +27 -5
- geth/mixins.py +54 -29
- geth/process.py +148 -124
- geth/py.typed +0 -0
- geth/reset.py +40 -16
- geth/types.py +65 -0
- geth/utils/encoding.py +36 -24
- geth/utils/filesystem.py +8 -15
- geth/utils/networking.py +18 -6
- geth/utils/proc.py +13 -3
- geth/utils/thread.py +5 -1
- geth/utils/timeout.py +39 -13
- geth/utils/validation.py +179 -0
- geth/wrapper.py +120 -169
- {py_geth-4.2.0.dist-info → py_geth-5.2.0.dist-info}/LICENSE +1 -1
- {py_geth-4.2.0.dist-info → py_geth-5.2.0.dist-info}/METADATA +54 -63
- py_geth-5.2.0.dist-info/RECORD +27 -0
- {py_geth-4.2.0.dist-info → py_geth-5.2.0.dist-info}/WHEEL +1 -1
- geth/utils/dag.py +0 -45
- py_geth-4.2.0.dist-info/RECORD +0 -25
- {py_geth-4.2.0.dist-info → py_geth-5.2.0.dist-info}/top_level.txt +0 -0
geth/install.py
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
"""
|
2
2
|
Install geth
|
3
3
|
"""
|
4
|
+
from __future__ import (
|
5
|
+
annotations,
|
6
|
+
)
|
7
|
+
|
4
8
|
import contextlib
|
5
9
|
import functools
|
6
10
|
import os
|
@@ -8,28 +12,40 @@ import stat
|
|
8
12
|
import subprocess
|
9
13
|
import sys
|
10
14
|
import tarfile
|
15
|
+
from typing import (
|
16
|
+
Any,
|
17
|
+
Generator,
|
18
|
+
)
|
19
|
+
|
20
|
+
import requests
|
21
|
+
from requests.exceptions import (
|
22
|
+
ConnectionError,
|
23
|
+
HTTPError,
|
24
|
+
Timeout,
|
25
|
+
)
|
26
|
+
|
27
|
+
from geth.exceptions import (
|
28
|
+
PyGethException,
|
29
|
+
PyGethKeyError,
|
30
|
+
PyGethOSError,
|
31
|
+
PyGethValueError,
|
32
|
+
)
|
33
|
+
from geth.types import (
|
34
|
+
IO_Any,
|
35
|
+
)
|
11
36
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
V1_13_2 = "v1.13.2"
|
25
|
-
V1_13_3 = "v1.13.3"
|
26
|
-
V1_13_4 = "v1.13.4"
|
27
|
-
V1_13_5 = "v1.13.5"
|
28
|
-
V1_13_6 = "v1.13.6"
|
29
|
-
V1_13_7 = "v1.13.7"
|
30
|
-
V1_13_8 = "v1.13.8"
|
31
|
-
V1_13_9 = "v1.13.9"
|
32
|
-
V1_13_10 = "v1.13.10"
|
37
|
+
V1_14_0 = "v1.14.0"
|
38
|
+
V1_14_2 = "v1.14.2"
|
39
|
+
V1_14_3 = "v1.14.3"
|
40
|
+
V1_14_4 = "v1.14.4"
|
41
|
+
V1_14_5 = "v1.14.5"
|
42
|
+
V1_14_6 = "v1.14.6"
|
43
|
+
V1_14_7 = "v1.14.7"
|
44
|
+
V1_14_8 = "v1.14.8"
|
45
|
+
V1_14_9 = "v1.14.9"
|
46
|
+
V1_14_10 = "v1.14.10"
|
47
|
+
V1_14_11 = "v1.14.11"
|
48
|
+
V1_14_12 = "v1.14.12"
|
33
49
|
|
34
50
|
|
35
51
|
LINUX = "linux"
|
@@ -41,7 +57,7 @@ WINDOWS = "win32"
|
|
41
57
|
# System utilities.
|
42
58
|
#
|
43
59
|
@contextlib.contextmanager
|
44
|
-
def chdir(path):
|
60
|
+
def chdir(path: str) -> Generator[None, None, None]:
|
45
61
|
original_path = os.getcwd()
|
46
62
|
try:
|
47
63
|
os.chdir(path)
|
@@ -50,7 +66,7 @@ def chdir(path):
|
|
50
66
|
os.chdir(original_path)
|
51
67
|
|
52
68
|
|
53
|
-
def get_platform():
|
69
|
+
def get_platform() -> str:
|
54
70
|
if sys.platform.startswith("linux"):
|
55
71
|
return LINUX
|
56
72
|
elif sys.platform == OSX:
|
@@ -58,11 +74,11 @@ def get_platform():
|
|
58
74
|
elif sys.platform == WINDOWS:
|
59
75
|
return WINDOWS
|
60
76
|
else:
|
61
|
-
raise
|
77
|
+
raise PyGethKeyError(f"Unknown platform: {sys.platform}")
|
62
78
|
|
63
79
|
|
64
|
-
def is_executable_available(program):
|
65
|
-
def is_exe(fpath):
|
80
|
+
def is_executable_available(program: str) -> bool:
|
81
|
+
def is_exe(fpath: str) -> bool:
|
66
82
|
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
67
83
|
|
68
84
|
fpath = os.path.dirname(program)
|
@@ -79,7 +95,7 @@ def is_executable_available(program):
|
|
79
95
|
return False
|
80
96
|
|
81
97
|
|
82
|
-
def ensure_path_exists(dir_path):
|
98
|
+
def ensure_path_exists(dir_path: str) -> bool:
|
83
99
|
"""
|
84
100
|
Make sure that a path exists
|
85
101
|
"""
|
@@ -89,13 +105,16 @@ def ensure_path_exists(dir_path):
|
|
89
105
|
return False
|
90
106
|
|
91
107
|
|
92
|
-
def ensure_parent_dir_exists(path):
|
108
|
+
def ensure_parent_dir_exists(path: str) -> None:
|
93
109
|
ensure_path_exists(os.path.dirname(path))
|
94
110
|
|
95
111
|
|
96
112
|
def check_subprocess_call(
|
97
|
-
command
|
98
|
-
|
113
|
+
command: list[str],
|
114
|
+
message: str | None = None,
|
115
|
+
stderr: IO_Any = subprocess.STDOUT,
|
116
|
+
**proc_kwargs: Any,
|
117
|
+
) -> int:
|
99
118
|
if message:
|
100
119
|
print(message)
|
101
120
|
print(f"Executing: {' '.join(command)}")
|
@@ -104,8 +123,11 @@ def check_subprocess_call(
|
|
104
123
|
|
105
124
|
|
106
125
|
def check_subprocess_output(
|
107
|
-
command
|
108
|
-
|
126
|
+
command: list[str],
|
127
|
+
message: str | None = None,
|
128
|
+
stderr: IO_Any = subprocess.STDOUT,
|
129
|
+
**proc_kwargs: Any,
|
130
|
+
) -> Any:
|
109
131
|
if message:
|
110
132
|
print(message)
|
111
133
|
print(f"Executing: {' '.join(command)}")
|
@@ -113,23 +135,23 @@ def check_subprocess_output(
|
|
113
135
|
return subprocess.check_output(command, stderr=stderr, **proc_kwargs)
|
114
136
|
|
115
137
|
|
116
|
-
def chmod_plus_x(executable_path):
|
138
|
+
def chmod_plus_x(executable_path: str) -> None:
|
117
139
|
current_st = os.stat(executable_path)
|
118
140
|
os.chmod(executable_path, current_st.st_mode | stat.S_IEXEC)
|
119
141
|
|
120
142
|
|
121
|
-
def get_go_executable_path():
|
143
|
+
def get_go_executable_path() -> str:
|
122
144
|
return os.environ.get("GO_BINARY", "go")
|
123
145
|
|
124
146
|
|
125
|
-
def is_go_available():
|
147
|
+
def is_go_available() -> bool:
|
126
148
|
return is_executable_available(get_go_executable_path())
|
127
149
|
|
128
150
|
|
129
151
|
#
|
130
152
|
# Installation filesystem path utilities
|
131
153
|
#
|
132
|
-
def get_base_install_path(identifier):
|
154
|
+
def get_base_install_path(identifier: str) -> str:
|
133
155
|
if "GETH_BASE_INSTALL_PATH" in os.environ:
|
134
156
|
return os.path.join(
|
135
157
|
os.environ["GETH_BASE_INSTALL_PATH"],
|
@@ -145,21 +167,21 @@ def get_base_install_path(identifier):
|
|
145
167
|
)
|
146
168
|
|
147
169
|
|
148
|
-
def get_source_code_archive_path(identifier):
|
170
|
+
def get_source_code_archive_path(identifier: str) -> str:
|
149
171
|
return os.path.join(
|
150
172
|
get_base_install_path(identifier),
|
151
173
|
"release.tar.gz",
|
152
174
|
)
|
153
175
|
|
154
176
|
|
155
|
-
def get_source_code_extract_path(identifier):
|
177
|
+
def get_source_code_extract_path(identifier: str) -> str:
|
156
178
|
return os.path.join(
|
157
179
|
get_base_install_path(identifier),
|
158
180
|
"source",
|
159
181
|
)
|
160
182
|
|
161
183
|
|
162
|
-
def get_source_code_path(identifier):
|
184
|
+
def get_source_code_path(identifier: str) -> str:
|
163
185
|
return os.path.join(
|
164
186
|
get_base_install_path(identifier),
|
165
187
|
"source",
|
@@ -167,7 +189,7 @@ def get_source_code_path(identifier):
|
|
167
189
|
)
|
168
190
|
|
169
191
|
|
170
|
-
def get_build_path(identifier):
|
192
|
+
def get_build_path(identifier: str) -> str:
|
171
193
|
source_code_path = get_source_code_path(identifier)
|
172
194
|
return os.path.join(
|
173
195
|
source_code_path,
|
@@ -175,7 +197,7 @@ def get_build_path(identifier):
|
|
175
197
|
)
|
176
198
|
|
177
199
|
|
178
|
-
def get_built_executable_path(identifier):
|
200
|
+
def get_built_executable_path(identifier: str) -> str:
|
179
201
|
build_path = get_build_path(identifier)
|
180
202
|
return os.path.join(
|
181
203
|
build_path,
|
@@ -184,7 +206,7 @@ def get_built_executable_path(identifier):
|
|
184
206
|
)
|
185
207
|
|
186
208
|
|
187
|
-
def get_executable_path(identifier):
|
209
|
+
def get_executable_path(identifier: str) -> str:
|
188
210
|
base_install_path = get_base_install_path(identifier)
|
189
211
|
return os.path.join(
|
190
212
|
base_install_path,
|
@@ -201,29 +223,27 @@ DOWNLOAD_SOURCE_CODE_URI_TEMPLATE = (
|
|
201
223
|
)
|
202
224
|
|
203
225
|
|
204
|
-
def download_source_code_release(identifier):
|
226
|
+
def download_source_code_release(identifier: str) -> None:
|
205
227
|
download_uri = DOWNLOAD_SOURCE_CODE_URI_TEMPLATE.format(identifier)
|
206
228
|
source_code_archive_path = get_source_code_archive_path(identifier)
|
207
229
|
|
208
230
|
ensure_parent_dir_exists(source_code_archive_path)
|
231
|
+
try:
|
232
|
+
response = requests.get(download_uri)
|
233
|
+
response.raise_for_status()
|
234
|
+
with open(source_code_archive_path, "wb") as f:
|
235
|
+
f.write(response.content)
|
209
236
|
|
210
|
-
|
211
|
-
"wget",
|
212
|
-
download_uri,
|
213
|
-
"-c", # resume previously incomplete download.
|
214
|
-
"-O",
|
215
|
-
source_code_archive_path,
|
216
|
-
]
|
217
|
-
|
218
|
-
return check_subprocess_call(
|
219
|
-
command,
|
220
|
-
message=f"Downloading source code release from {download_uri}",
|
221
|
-
)
|
237
|
+
print(f"Downloading source code release from {download_uri}")
|
222
238
|
|
239
|
+
except (HTTPError, Timeout, ConnectionError) as e:
|
240
|
+
raise PyGethException(
|
241
|
+
f"An error occurred while downloading from {download_uri}: {e}"
|
242
|
+
)
|
223
243
|
|
224
|
-
def extract_source_code_release(identifier):
|
225
|
-
source_code_archive_path = get_source_code_archive_path(identifier)
|
226
244
|
|
245
|
+
def extract_source_code_release(identifier: str) -> None:
|
246
|
+
source_code_archive_path = get_source_code_archive_path(identifier)
|
227
247
|
source_code_extract_path = get_source_code_extract_path(identifier)
|
228
248
|
ensure_path_exists(source_code_extract_path)
|
229
249
|
|
@@ -233,7 +253,7 @@ def extract_source_code_release(identifier):
|
|
233
253
|
|
234
254
|
with tarfile.open(source_code_archive_path, "r:gz") as archive_file:
|
235
255
|
|
236
|
-
def is_within_directory(directory, target):
|
256
|
+
def is_within_directory(directory: str, target: str) -> bool:
|
237
257
|
abs_directory = os.path.abspath(directory)
|
238
258
|
abs_target = os.path.abspath(target)
|
239
259
|
|
@@ -241,20 +261,20 @@ def extract_source_code_release(identifier):
|
|
241
261
|
|
242
262
|
return prefix == abs_directory
|
243
263
|
|
244
|
-
def safe_extract(tar, path="."):
|
264
|
+
def safe_extract(tar: tarfile.TarFile, path: str = ".") -> None:
|
245
265
|
for member in tar.getmembers():
|
246
266
|
member_path = os.path.join(path, member.name)
|
247
267
|
if not is_within_directory(path, member_path):
|
248
|
-
raise
|
268
|
+
raise PyGethException("Attempted Path Traversal in Tar File")
|
249
269
|
|
250
270
|
tar.extractall(path)
|
251
271
|
|
252
272
|
safe_extract(archive_file, source_code_extract_path)
|
253
273
|
|
254
274
|
|
255
|
-
def build_from_source_code(identifier):
|
275
|
+
def build_from_source_code(identifier: str) -> None:
|
256
276
|
if not is_go_available():
|
257
|
-
raise
|
277
|
+
raise PyGethOSError(
|
258
278
|
"The `go` runtime was not found but is required to build geth. If "
|
259
279
|
"the `go` executable is not in your $PATH you can specify the path "
|
260
280
|
"using the environment variable GO_BINARY to specify the path."
|
@@ -271,7 +291,7 @@ def build_from_source_code(identifier):
|
|
271
291
|
|
272
292
|
built_executable_path = get_built_executable_path(identifier)
|
273
293
|
if not os.path.exists(built_executable_path):
|
274
|
-
raise
|
294
|
+
raise PyGethOSError(
|
275
295
|
"Built executable not found in expected location: "
|
276
296
|
f"{built_executable_path}"
|
277
297
|
)
|
@@ -284,12 +304,14 @@ def build_from_source_code(identifier):
|
|
284
304
|
if os.path.islink(executable_path):
|
285
305
|
os.remove(executable_path)
|
286
306
|
else:
|
287
|
-
raise
|
307
|
+
raise PyGethOSError(
|
308
|
+
f"Non-symlink file already present at `{executable_path}`"
|
309
|
+
)
|
288
310
|
os.symlink(built_executable_path, executable_path)
|
289
311
|
chmod_plus_x(executable_path)
|
290
312
|
|
291
313
|
|
292
|
-
def install_from_source_code_release(identifier):
|
314
|
+
def install_from_source_code_release(identifier: str) -> None:
|
293
315
|
download_source_code_release(identifier)
|
294
316
|
extract_source_code_release(identifier)
|
295
317
|
build_from_source_code(identifier)
|
@@ -307,91 +329,63 @@ def install_from_source_code_release(identifier):
|
|
307
329
|
print(f"geth successfully installed at: {executable_path}\n\n{version_output}\n\n")
|
308
330
|
|
309
331
|
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
install_v1_13_2 = functools.partial(install_from_source_code_release, V1_13_2)
|
323
|
-
install_v1_13_3 = functools.partial(install_from_source_code_release, V1_13_3)
|
324
|
-
install_v1_13_4 = functools.partial(install_from_source_code_release, V1_13_4)
|
325
|
-
install_v1_13_5 = functools.partial(install_from_source_code_release, V1_13_5)
|
326
|
-
install_v1_13_6 = functools.partial(install_from_source_code_release, V1_13_6)
|
327
|
-
install_v1_13_7 = functools.partial(install_from_source_code_release, V1_13_7)
|
328
|
-
install_v1_13_8 = functools.partial(install_from_source_code_release, V1_13_8)
|
329
|
-
install_v1_13_9 = functools.partial(install_from_source_code_release, V1_13_9)
|
330
|
-
install_v1_13_10 = functools.partial(install_from_source_code_release, V1_13_10)
|
331
|
-
|
332
|
+
install_v1_14_0 = functools.partial(install_from_source_code_release, V1_14_0)
|
333
|
+
install_v1_14_2 = functools.partial(install_from_source_code_release, V1_14_2)
|
334
|
+
install_v1_14_3 = functools.partial(install_from_source_code_release, V1_14_3)
|
335
|
+
install_v1_14_4 = functools.partial(install_from_source_code_release, V1_14_4)
|
336
|
+
install_v1_14_5 = functools.partial(install_from_source_code_release, V1_14_5)
|
337
|
+
install_v1_14_6 = functools.partial(install_from_source_code_release, V1_14_6)
|
338
|
+
install_v1_14_7 = functools.partial(install_from_source_code_release, V1_14_7)
|
339
|
+
install_v1_14_8 = functools.partial(install_from_source_code_release, V1_14_8)
|
340
|
+
install_v1_14_9 = functools.partial(install_from_source_code_release, V1_14_9)
|
341
|
+
install_v1_14_10 = functools.partial(install_from_source_code_release, V1_14_10)
|
342
|
+
install_v1_14_11 = functools.partial(install_from_source_code_release, V1_14_11)
|
343
|
+
install_v1_14_12 = functools.partial(install_from_source_code_release, V1_14_12)
|
332
344
|
|
333
345
|
INSTALL_FUNCTIONS = {
|
334
346
|
LINUX: {
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
V1_13_2: install_v1_13_2,
|
348
|
-
V1_13_3: install_v1_13_3,
|
349
|
-
V1_13_4: install_v1_13_4,
|
350
|
-
V1_13_5: install_v1_13_5,
|
351
|
-
V1_13_6: install_v1_13_6,
|
352
|
-
V1_13_7: install_v1_13_7,
|
353
|
-
V1_13_8: install_v1_13_8,
|
354
|
-
V1_13_9: install_v1_13_9,
|
355
|
-
V1_13_10: install_v1_13_10,
|
347
|
+
V1_14_0: install_v1_14_0,
|
348
|
+
V1_14_2: install_v1_14_2,
|
349
|
+
V1_14_3: install_v1_14_3,
|
350
|
+
V1_14_4: install_v1_14_4,
|
351
|
+
V1_14_5: install_v1_14_5,
|
352
|
+
V1_14_6: install_v1_14_6,
|
353
|
+
V1_14_7: install_v1_14_7,
|
354
|
+
V1_14_8: install_v1_14_8,
|
355
|
+
V1_14_9: install_v1_14_9,
|
356
|
+
V1_14_10: install_v1_14_10,
|
357
|
+
V1_14_11: install_v1_14_11,
|
358
|
+
V1_14_12: install_v1_14_12,
|
356
359
|
},
|
357
360
|
OSX: {
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
V1_13_2: install_v1_13_2,
|
371
|
-
V1_13_3: install_v1_13_3,
|
372
|
-
V1_13_4: install_v1_13_4,
|
373
|
-
V1_13_5: install_v1_13_5,
|
374
|
-
V1_13_6: install_v1_13_6,
|
375
|
-
V1_13_7: install_v1_13_7,
|
376
|
-
V1_13_8: install_v1_13_8,
|
377
|
-
V1_13_9: install_v1_13_9,
|
378
|
-
V1_13_10: install_v1_13_10,
|
361
|
+
V1_14_0: install_v1_14_0,
|
362
|
+
V1_14_2: install_v1_14_2,
|
363
|
+
V1_14_3: install_v1_14_3,
|
364
|
+
V1_14_4: install_v1_14_4,
|
365
|
+
V1_14_5: install_v1_14_5,
|
366
|
+
V1_14_6: install_v1_14_6,
|
367
|
+
V1_14_7: install_v1_14_7,
|
368
|
+
V1_14_8: install_v1_14_8,
|
369
|
+
V1_14_9: install_v1_14_9,
|
370
|
+
V1_14_10: install_v1_14_10,
|
371
|
+
V1_14_11: install_v1_14_11,
|
372
|
+
V1_14_12: install_v1_14_12,
|
379
373
|
},
|
380
374
|
}
|
381
375
|
|
382
376
|
|
383
|
-
def install_geth(identifier, platform=None):
|
377
|
+
def install_geth(identifier: str, platform: str | None = None) -> None:
|
384
378
|
if platform is None:
|
385
379
|
platform = get_platform()
|
386
380
|
|
387
381
|
if platform not in INSTALL_FUNCTIONS:
|
388
|
-
raise
|
382
|
+
raise PyGethValueError(
|
389
383
|
"Installation of go-ethereum is not supported on your platform "
|
390
384
|
f"({platform}). Supported platforms are: "
|
391
385
|
f"{', '.join(sorted(INSTALL_FUNCTIONS.keys()))}"
|
392
386
|
)
|
393
387
|
elif identifier not in INSTALL_FUNCTIONS[platform]:
|
394
|
-
raise
|
388
|
+
raise PyGethValueError(
|
395
389
|
f"Installation of geth=={identifier} is not supported. Must be one of "
|
396
390
|
f"{', '.join(sorted(INSTALL_FUNCTIONS[platform].keys()))}"
|
397
391
|
)
|
geth/main.py
CHANGED
@@ -1,6 +1,24 @@
|
|
1
|
+
from __future__ import (
|
2
|
+
annotations,
|
3
|
+
)
|
4
|
+
|
1
5
|
import re
|
2
6
|
|
3
7
|
import semantic_version
|
8
|
+
from typing_extensions import (
|
9
|
+
Unpack,
|
10
|
+
)
|
11
|
+
|
12
|
+
from geth.exceptions import (
|
13
|
+
PyGethTypeError,
|
14
|
+
PyGethValueError,
|
15
|
+
)
|
16
|
+
from geth.types import (
|
17
|
+
GethKwargsTypedDict,
|
18
|
+
)
|
19
|
+
from geth.utils.validation import (
|
20
|
+
validate_geth_kwargs,
|
21
|
+
)
|
4
22
|
|
5
23
|
from .utils.encoding import (
|
6
24
|
force_text,
|
@@ -10,25 +28,29 @@ from .wrapper import (
|
|
10
28
|
)
|
11
29
|
|
12
30
|
|
13
|
-
def get_geth_version_info_string(**geth_kwargs):
|
31
|
+
def get_geth_version_info_string(**geth_kwargs: Unpack[GethKwargsTypedDict]) -> str:
|
14
32
|
if "suffix_args" in geth_kwargs:
|
15
|
-
raise
|
33
|
+
raise PyGethTypeError(
|
16
34
|
"The `get_geth_version` function cannot be called with the "
|
17
35
|
"`suffix_args` parameter"
|
18
36
|
)
|
19
37
|
geth_kwargs["suffix_args"] = ["version"]
|
38
|
+
validate_geth_kwargs(geth_kwargs)
|
20
39
|
stdoutdata, stderrdata, command, proc = geth_wrapper(**geth_kwargs)
|
21
|
-
return stdoutdata
|
40
|
+
return stdoutdata.decode("utf-8")
|
22
41
|
|
23
42
|
|
24
43
|
VERSION_REGEX = r"Version: (.*)\n"
|
25
44
|
|
26
45
|
|
27
|
-
def get_geth_version(
|
46
|
+
def get_geth_version(
|
47
|
+
**geth_kwargs: Unpack[GethKwargsTypedDict],
|
48
|
+
) -> semantic_version.Version:
|
49
|
+
validate_geth_kwargs(geth_kwargs)
|
28
50
|
version_info_string = get_geth_version_info_string(**geth_kwargs)
|
29
51
|
version_match = re.search(VERSION_REGEX, force_text(version_info_string, "utf8"))
|
30
52
|
if not version_match:
|
31
|
-
raise
|
53
|
+
raise PyGethValueError(
|
32
54
|
f"Did not match version string in geth output:\n{version_info_string}"
|
33
55
|
)
|
34
56
|
version_string = version_match.groups()[0]
|