py-geth 4.3.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 -136
- 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.3.0.dist-info → py_geth-5.2.0.dist-info}/LICENSE +1 -1
- {py_geth-4.3.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.3.0.dist-info → py_geth-5.2.0.dist-info}/WHEEL +1 -1
- geth/utils/dag.py +0 -45
- py_geth-4.3.0.dist-info/RECORD +0 -25
- {py_geth-4.3.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,29 +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"
|
33
|
-
V1_13_11 = "v1.13.11"
|
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"
|
34
49
|
|
35
50
|
|
36
51
|
LINUX = "linux"
|
@@ -42,7 +57,7 @@ WINDOWS = "win32"
|
|
42
57
|
# System utilities.
|
43
58
|
#
|
44
59
|
@contextlib.contextmanager
|
45
|
-
def chdir(path):
|
60
|
+
def chdir(path: str) -> Generator[None, None, None]:
|
46
61
|
original_path = os.getcwd()
|
47
62
|
try:
|
48
63
|
os.chdir(path)
|
@@ -51,7 +66,7 @@ def chdir(path):
|
|
51
66
|
os.chdir(original_path)
|
52
67
|
|
53
68
|
|
54
|
-
def get_platform():
|
69
|
+
def get_platform() -> str:
|
55
70
|
if sys.platform.startswith("linux"):
|
56
71
|
return LINUX
|
57
72
|
elif sys.platform == OSX:
|
@@ -59,11 +74,11 @@ def get_platform():
|
|
59
74
|
elif sys.platform == WINDOWS:
|
60
75
|
return WINDOWS
|
61
76
|
else:
|
62
|
-
raise
|
77
|
+
raise PyGethKeyError(f"Unknown platform: {sys.platform}")
|
63
78
|
|
64
79
|
|
65
|
-
def is_executable_available(program):
|
66
|
-
def is_exe(fpath):
|
80
|
+
def is_executable_available(program: str) -> bool:
|
81
|
+
def is_exe(fpath: str) -> bool:
|
67
82
|
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
68
83
|
|
69
84
|
fpath = os.path.dirname(program)
|
@@ -80,7 +95,7 @@ def is_executable_available(program):
|
|
80
95
|
return False
|
81
96
|
|
82
97
|
|
83
|
-
def ensure_path_exists(dir_path):
|
98
|
+
def ensure_path_exists(dir_path: str) -> bool:
|
84
99
|
"""
|
85
100
|
Make sure that a path exists
|
86
101
|
"""
|
@@ -90,13 +105,16 @@ def ensure_path_exists(dir_path):
|
|
90
105
|
return False
|
91
106
|
|
92
107
|
|
93
|
-
def ensure_parent_dir_exists(path):
|
108
|
+
def ensure_parent_dir_exists(path: str) -> None:
|
94
109
|
ensure_path_exists(os.path.dirname(path))
|
95
110
|
|
96
111
|
|
97
112
|
def check_subprocess_call(
|
98
|
-
command
|
99
|
-
|
113
|
+
command: list[str],
|
114
|
+
message: str | None = None,
|
115
|
+
stderr: IO_Any = subprocess.STDOUT,
|
116
|
+
**proc_kwargs: Any,
|
117
|
+
) -> int:
|
100
118
|
if message:
|
101
119
|
print(message)
|
102
120
|
print(f"Executing: {' '.join(command)}")
|
@@ -105,8 +123,11 @@ def check_subprocess_call(
|
|
105
123
|
|
106
124
|
|
107
125
|
def check_subprocess_output(
|
108
|
-
command
|
109
|
-
|
126
|
+
command: list[str],
|
127
|
+
message: str | None = None,
|
128
|
+
stderr: IO_Any = subprocess.STDOUT,
|
129
|
+
**proc_kwargs: Any,
|
130
|
+
) -> Any:
|
110
131
|
if message:
|
111
132
|
print(message)
|
112
133
|
print(f"Executing: {' '.join(command)}")
|
@@ -114,23 +135,23 @@ def check_subprocess_output(
|
|
114
135
|
return subprocess.check_output(command, stderr=stderr, **proc_kwargs)
|
115
136
|
|
116
137
|
|
117
|
-
def chmod_plus_x(executable_path):
|
138
|
+
def chmod_plus_x(executable_path: str) -> None:
|
118
139
|
current_st = os.stat(executable_path)
|
119
140
|
os.chmod(executable_path, current_st.st_mode | stat.S_IEXEC)
|
120
141
|
|
121
142
|
|
122
|
-
def get_go_executable_path():
|
143
|
+
def get_go_executable_path() -> str:
|
123
144
|
return os.environ.get("GO_BINARY", "go")
|
124
145
|
|
125
146
|
|
126
|
-
def is_go_available():
|
147
|
+
def is_go_available() -> bool:
|
127
148
|
return is_executable_available(get_go_executable_path())
|
128
149
|
|
129
150
|
|
130
151
|
#
|
131
152
|
# Installation filesystem path utilities
|
132
153
|
#
|
133
|
-
def get_base_install_path(identifier):
|
154
|
+
def get_base_install_path(identifier: str) -> str:
|
134
155
|
if "GETH_BASE_INSTALL_PATH" in os.environ:
|
135
156
|
return os.path.join(
|
136
157
|
os.environ["GETH_BASE_INSTALL_PATH"],
|
@@ -146,21 +167,21 @@ def get_base_install_path(identifier):
|
|
146
167
|
)
|
147
168
|
|
148
169
|
|
149
|
-
def get_source_code_archive_path(identifier):
|
170
|
+
def get_source_code_archive_path(identifier: str) -> str:
|
150
171
|
return os.path.join(
|
151
172
|
get_base_install_path(identifier),
|
152
173
|
"release.tar.gz",
|
153
174
|
)
|
154
175
|
|
155
176
|
|
156
|
-
def get_source_code_extract_path(identifier):
|
177
|
+
def get_source_code_extract_path(identifier: str) -> str:
|
157
178
|
return os.path.join(
|
158
179
|
get_base_install_path(identifier),
|
159
180
|
"source",
|
160
181
|
)
|
161
182
|
|
162
183
|
|
163
|
-
def get_source_code_path(identifier):
|
184
|
+
def get_source_code_path(identifier: str) -> str:
|
164
185
|
return os.path.join(
|
165
186
|
get_base_install_path(identifier),
|
166
187
|
"source",
|
@@ -168,7 +189,7 @@ def get_source_code_path(identifier):
|
|
168
189
|
)
|
169
190
|
|
170
191
|
|
171
|
-
def get_build_path(identifier):
|
192
|
+
def get_build_path(identifier: str) -> str:
|
172
193
|
source_code_path = get_source_code_path(identifier)
|
173
194
|
return os.path.join(
|
174
195
|
source_code_path,
|
@@ -176,7 +197,7 @@ def get_build_path(identifier):
|
|
176
197
|
)
|
177
198
|
|
178
199
|
|
179
|
-
def get_built_executable_path(identifier):
|
200
|
+
def get_built_executable_path(identifier: str) -> str:
|
180
201
|
build_path = get_build_path(identifier)
|
181
202
|
return os.path.join(
|
182
203
|
build_path,
|
@@ -185,7 +206,7 @@ def get_built_executable_path(identifier):
|
|
185
206
|
)
|
186
207
|
|
187
208
|
|
188
|
-
def get_executable_path(identifier):
|
209
|
+
def get_executable_path(identifier: str) -> str:
|
189
210
|
base_install_path = get_base_install_path(identifier)
|
190
211
|
return os.path.join(
|
191
212
|
base_install_path,
|
@@ -202,29 +223,27 @@ DOWNLOAD_SOURCE_CODE_URI_TEMPLATE = (
|
|
202
223
|
)
|
203
224
|
|
204
225
|
|
205
|
-
def download_source_code_release(identifier):
|
226
|
+
def download_source_code_release(identifier: str) -> None:
|
206
227
|
download_uri = DOWNLOAD_SOURCE_CODE_URI_TEMPLATE.format(identifier)
|
207
228
|
source_code_archive_path = get_source_code_archive_path(identifier)
|
208
229
|
|
209
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)
|
210
236
|
|
211
|
-
|
212
|
-
"wget",
|
213
|
-
download_uri,
|
214
|
-
"-c", # resume previously incomplete download.
|
215
|
-
"-O",
|
216
|
-
source_code_archive_path,
|
217
|
-
]
|
218
|
-
|
219
|
-
return check_subprocess_call(
|
220
|
-
command,
|
221
|
-
message=f"Downloading source code release from {download_uri}",
|
222
|
-
)
|
237
|
+
print(f"Downloading source code release from {download_uri}")
|
223
238
|
|
239
|
+
except (HTTPError, Timeout, ConnectionError) as e:
|
240
|
+
raise PyGethException(
|
241
|
+
f"An error occurred while downloading from {download_uri}: {e}"
|
242
|
+
)
|
224
243
|
|
225
|
-
def extract_source_code_release(identifier):
|
226
|
-
source_code_archive_path = get_source_code_archive_path(identifier)
|
227
244
|
|
245
|
+
def extract_source_code_release(identifier: str) -> None:
|
246
|
+
source_code_archive_path = get_source_code_archive_path(identifier)
|
228
247
|
source_code_extract_path = get_source_code_extract_path(identifier)
|
229
248
|
ensure_path_exists(source_code_extract_path)
|
230
249
|
|
@@ -234,7 +253,7 @@ def extract_source_code_release(identifier):
|
|
234
253
|
|
235
254
|
with tarfile.open(source_code_archive_path, "r:gz") as archive_file:
|
236
255
|
|
237
|
-
def is_within_directory(directory, target):
|
256
|
+
def is_within_directory(directory: str, target: str) -> bool:
|
238
257
|
abs_directory = os.path.abspath(directory)
|
239
258
|
abs_target = os.path.abspath(target)
|
240
259
|
|
@@ -242,20 +261,20 @@ def extract_source_code_release(identifier):
|
|
242
261
|
|
243
262
|
return prefix == abs_directory
|
244
263
|
|
245
|
-
def safe_extract(tar, path="."):
|
264
|
+
def safe_extract(tar: tarfile.TarFile, path: str = ".") -> None:
|
246
265
|
for member in tar.getmembers():
|
247
266
|
member_path = os.path.join(path, member.name)
|
248
267
|
if not is_within_directory(path, member_path):
|
249
|
-
raise
|
268
|
+
raise PyGethException("Attempted Path Traversal in Tar File")
|
250
269
|
|
251
270
|
tar.extractall(path)
|
252
271
|
|
253
272
|
safe_extract(archive_file, source_code_extract_path)
|
254
273
|
|
255
274
|
|
256
|
-
def build_from_source_code(identifier):
|
275
|
+
def build_from_source_code(identifier: str) -> None:
|
257
276
|
if not is_go_available():
|
258
|
-
raise
|
277
|
+
raise PyGethOSError(
|
259
278
|
"The `go` runtime was not found but is required to build geth. If "
|
260
279
|
"the `go` executable is not in your $PATH you can specify the path "
|
261
280
|
"using the environment variable GO_BINARY to specify the path."
|
@@ -272,7 +291,7 @@ def build_from_source_code(identifier):
|
|
272
291
|
|
273
292
|
built_executable_path = get_built_executable_path(identifier)
|
274
293
|
if not os.path.exists(built_executable_path):
|
275
|
-
raise
|
294
|
+
raise PyGethOSError(
|
276
295
|
"Built executable not found in expected location: "
|
277
296
|
f"{built_executable_path}"
|
278
297
|
)
|
@@ -285,12 +304,14 @@ def build_from_source_code(identifier):
|
|
285
304
|
if os.path.islink(executable_path):
|
286
305
|
os.remove(executable_path)
|
287
306
|
else:
|
288
|
-
raise
|
307
|
+
raise PyGethOSError(
|
308
|
+
f"Non-symlink file already present at `{executable_path}`"
|
309
|
+
)
|
289
310
|
os.symlink(built_executable_path, executable_path)
|
290
311
|
chmod_plus_x(executable_path)
|
291
312
|
|
292
313
|
|
293
|
-
def install_from_source_code_release(identifier):
|
314
|
+
def install_from_source_code_release(identifier: str) -> None:
|
294
315
|
download_source_code_release(identifier)
|
295
316
|
extract_source_code_release(identifier)
|
296
317
|
build_from_source_code(identifier)
|
@@ -308,94 +329,63 @@ def install_from_source_code_release(identifier):
|
|
308
329
|
print(f"geth successfully installed at: {executable_path}\n\n{version_output}\n\n")
|
309
330
|
|
310
331
|
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
install_v1_13_2 = functools.partial(install_from_source_code_release, V1_13_2)
|
324
|
-
install_v1_13_3 = functools.partial(install_from_source_code_release, V1_13_3)
|
325
|
-
install_v1_13_4 = functools.partial(install_from_source_code_release, V1_13_4)
|
326
|
-
install_v1_13_5 = functools.partial(install_from_source_code_release, V1_13_5)
|
327
|
-
install_v1_13_6 = functools.partial(install_from_source_code_release, V1_13_6)
|
328
|
-
install_v1_13_7 = functools.partial(install_from_source_code_release, V1_13_7)
|
329
|
-
install_v1_13_8 = functools.partial(install_from_source_code_release, V1_13_8)
|
330
|
-
install_v1_13_9 = functools.partial(install_from_source_code_release, V1_13_9)
|
331
|
-
install_v1_13_10 = functools.partial(install_from_source_code_release, V1_13_10)
|
332
|
-
install_v1_13_11 = functools.partial(install_from_source_code_release, V1_13_11)
|
333
|
-
|
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)
|
334
344
|
|
335
345
|
INSTALL_FUNCTIONS = {
|
336
346
|
LINUX: {
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
V1_13_2: install_v1_13_2,
|
350
|
-
V1_13_3: install_v1_13_3,
|
351
|
-
V1_13_4: install_v1_13_4,
|
352
|
-
V1_13_5: install_v1_13_5,
|
353
|
-
V1_13_6: install_v1_13_6,
|
354
|
-
V1_13_7: install_v1_13_7,
|
355
|
-
V1_13_8: install_v1_13_8,
|
356
|
-
V1_13_9: install_v1_13_9,
|
357
|
-
V1_13_10: install_v1_13_10,
|
358
|
-
V1_13_11: install_v1_13_11,
|
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,
|
359
359
|
},
|
360
360
|
OSX: {
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
V1_13_2: install_v1_13_2,
|
374
|
-
V1_13_3: install_v1_13_3,
|
375
|
-
V1_13_4: install_v1_13_4,
|
376
|
-
V1_13_5: install_v1_13_5,
|
377
|
-
V1_13_6: install_v1_13_6,
|
378
|
-
V1_13_7: install_v1_13_7,
|
379
|
-
V1_13_8: install_v1_13_8,
|
380
|
-
V1_13_9: install_v1_13_9,
|
381
|
-
V1_13_10: install_v1_13_10,
|
382
|
-
V1_13_11: install_v1_13_11,
|
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,
|
383
373
|
},
|
384
374
|
}
|
385
375
|
|
386
376
|
|
387
|
-
def install_geth(identifier, platform=None):
|
377
|
+
def install_geth(identifier: str, platform: str | None = None) -> None:
|
388
378
|
if platform is None:
|
389
379
|
platform = get_platform()
|
390
380
|
|
391
381
|
if platform not in INSTALL_FUNCTIONS:
|
392
|
-
raise
|
382
|
+
raise PyGethValueError(
|
393
383
|
"Installation of go-ethereum is not supported on your platform "
|
394
384
|
f"({platform}). Supported platforms are: "
|
395
385
|
f"{', '.join(sorted(INSTALL_FUNCTIONS.keys()))}"
|
396
386
|
)
|
397
387
|
elif identifier not in INSTALL_FUNCTIONS[platform]:
|
398
|
-
raise
|
388
|
+
raise PyGethValueError(
|
399
389
|
f"Installation of geth=={identifier} is not supported. Must be one of "
|
400
390
|
f"{', '.join(sorted(INSTALL_FUNCTIONS[platform].keys()))}"
|
401
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]
|