levistone 0.9.3__cp311-cp311-win_amd64.whl → 0.10.6__cp311-cp311-win_amd64.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.
Potentially problematic release.
This version of levistone might be problematic. Click here for more details.
- endstone/__init__.py +1 -1
- endstone/_internal/bootstrap/base.py +23 -0
- endstone/_internal/bootstrap/linux.py +0 -4
- endstone/_internal/bootstrap/windows.py +137 -9
- endstone/_internal/endstone_python.cp311-win_amd64.pyd +0 -0
- endstone/_internal/endstone_python.pyi +362 -81
- endstone/_internal/plugin_loader.py +13 -2
- endstone/_internal/version.py +2 -2
- endstone/actor.py +2 -2
- endstone/command.py +2 -2
- endstone/config/endstone.toml +9 -0
- endstone/event.py +20 -0
- endstone/form.py +2 -0
- endstone/permissions.py +9 -1
- endstone_runtime.dll +0 -0
- endstone_runtime.pdb +0 -0
- levistone-0.10.6.dist-info/METADATA +49 -0
- levistone-0.10.6.dist-info/RECORD +40 -0
- manifest.json +1 -1
- endstone/_internal/endstone_python.cp39-win_amd64.pyd +0 -0
- levistone-0.9.3.dist-info/METADATA +0 -250
- levistone-0.9.3.dist-info/RECORD +0 -39
- {levistone-0.9.3.dist-info → levistone-0.10.6.dist-info}/WHEEL +0 -0
- {levistone-0.9.3.dist-info → levistone-0.10.6.dist-info}/entry_points.txt +0 -0
- {levistone-0.9.3.dist-info → levistone-0.10.6.dist-info}/licenses/LICENSE +0 -0
- {levistone-0.9.3.dist-info → levistone-0.10.6.dist-info}/top_level.txt +0 -0
endstone/__init__.py
CHANGED
|
@@ -16,6 +16,7 @@ import click
|
|
|
16
16
|
import importlib_resources
|
|
17
17
|
import requests
|
|
18
18
|
import sentry_crashpad
|
|
19
|
+
import tomlkit
|
|
19
20
|
from packaging.version import Version
|
|
20
21
|
from rich.progress import BarColumn, DownloadColumn, Progress, TextColumn, TimeRemainingColumn
|
|
21
22
|
|
|
@@ -161,6 +162,28 @@ class Bootstrap:
|
|
|
161
162
|
ref = importlib_resources.files("endstone") / "config" / "endstone.toml"
|
|
162
163
|
with importlib_resources.as_file(ref) as path:
|
|
163
164
|
shutil.copy(path, self.config_path)
|
|
165
|
+
else:
|
|
166
|
+
ref = importlib_resources.files("endstone") / "config" / "endstone.toml"
|
|
167
|
+
with importlib_resources.as_file(ref) as path:
|
|
168
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
169
|
+
default_config = tomlkit.load(f)
|
|
170
|
+
|
|
171
|
+
with open(self.config_path, "r", encoding="utf-8") as f:
|
|
172
|
+
config = tomlkit.load(f)
|
|
173
|
+
|
|
174
|
+
def migrate_config(from_doc: tomlkit.TOMLDocument, to_doc: tomlkit.TOMLDocument) -> None:
|
|
175
|
+
for key, val in from_doc.items():
|
|
176
|
+
if key not in to_doc:
|
|
177
|
+
# if the user hasn’t set it, copy it (with comments!)
|
|
178
|
+
to_doc[key] = val
|
|
179
|
+
else:
|
|
180
|
+
# if both are tables, dive deeper
|
|
181
|
+
if isinstance(val, tomlkit.TOMLDocument) and isinstance(to_doc[key], tomlkit.TOMLDocument):
|
|
182
|
+
migrate_config(val, to_doc[key])
|
|
183
|
+
|
|
184
|
+
migrate_config(default_config, config)
|
|
185
|
+
with open(self.config_path, "w", encoding="utf-8") as f:
|
|
186
|
+
tomlkit.dump(config, f)
|
|
164
187
|
|
|
165
188
|
def _install(self) -> None:
|
|
166
189
|
"""
|
|
@@ -2,7 +2,6 @@ import ctypes.util
|
|
|
2
2
|
import os
|
|
3
3
|
import stat
|
|
4
4
|
import subprocess
|
|
5
|
-
import sys
|
|
6
5
|
from pathlib import Path
|
|
7
6
|
|
|
8
7
|
from endstone._internal.bootstrap.base import Bootstrap
|
|
@@ -41,9 +40,6 @@ class LinuxBootstrap(Bootstrap):
|
|
|
41
40
|
def _run(self, *args, **kwargs) -> int:
|
|
42
41
|
process = subprocess.Popen(
|
|
43
42
|
[str(self.executable_path.absolute())],
|
|
44
|
-
stdin=sys.stdin,
|
|
45
|
-
stdout=sys.stdout,
|
|
46
|
-
stderr=subprocess.STDOUT,
|
|
47
43
|
text=True,
|
|
48
44
|
encoding="utf-8",
|
|
49
45
|
cwd=str(self.server_path.absolute()),
|
|
@@ -1,9 +1,128 @@
|
|
|
1
|
+
import _winapi
|
|
1
2
|
import ctypes
|
|
2
3
|
import os
|
|
3
4
|
import subprocess
|
|
5
|
+
import warnings
|
|
6
|
+
from subprocess import STARTUPINFO, Handle, list2cmdline
|
|
4
7
|
|
|
8
|
+
from endstone._internal import _detours
|
|
5
9
|
from endstone._internal.bootstrap.base import Bootstrap
|
|
6
|
-
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PopenWithDll(subprocess.Popen):
|
|
13
|
+
def __init__(self, *args, **kwargs):
|
|
14
|
+
self.dll_names = kwargs.pop("dll_names", None)
|
|
15
|
+
super().__init__(*args, **kwargs)
|
|
16
|
+
|
|
17
|
+
def _execute_child(
|
|
18
|
+
self,
|
|
19
|
+
args,
|
|
20
|
+
executable,
|
|
21
|
+
preexec_fn,
|
|
22
|
+
close_fds,
|
|
23
|
+
pass_fds,
|
|
24
|
+
cwd,
|
|
25
|
+
env,
|
|
26
|
+
startupinfo,
|
|
27
|
+
creationflags,
|
|
28
|
+
shell,
|
|
29
|
+
p2cread,
|
|
30
|
+
p2cwrite,
|
|
31
|
+
c2pread,
|
|
32
|
+
c2pwrite,
|
|
33
|
+
errread,
|
|
34
|
+
errwrite,
|
|
35
|
+
unused_restore_signals,
|
|
36
|
+
unused_gid,
|
|
37
|
+
unused_gids,
|
|
38
|
+
unused_uid,
|
|
39
|
+
unused_umask,
|
|
40
|
+
unused_start_new_session,
|
|
41
|
+
unused_process_group,
|
|
42
|
+
):
|
|
43
|
+
"""Execute program (MS Windows version)"""
|
|
44
|
+
|
|
45
|
+
assert not pass_fds, "pass_fds not supported on Windows."
|
|
46
|
+
|
|
47
|
+
if isinstance(args, str):
|
|
48
|
+
pass
|
|
49
|
+
elif isinstance(args, bytes):
|
|
50
|
+
if shell:
|
|
51
|
+
raise TypeError("bytes args is not allowed on Windows")
|
|
52
|
+
args = list2cmdline([args])
|
|
53
|
+
elif isinstance(args, os.PathLike):
|
|
54
|
+
if shell:
|
|
55
|
+
raise TypeError("path-like args is not allowed when shell is true")
|
|
56
|
+
args = list2cmdline([args])
|
|
57
|
+
else:
|
|
58
|
+
args = list2cmdline(args)
|
|
59
|
+
|
|
60
|
+
if executable is not None:
|
|
61
|
+
executable = os.fsdecode(executable)
|
|
62
|
+
|
|
63
|
+
if startupinfo is None:
|
|
64
|
+
startupinfo = STARTUPINFO()
|
|
65
|
+
else:
|
|
66
|
+
startupinfo = startupinfo.copy()
|
|
67
|
+
|
|
68
|
+
use_std_handles = -1 not in (p2cread, c2pwrite, errwrite)
|
|
69
|
+
if use_std_handles:
|
|
70
|
+
startupinfo.dwFlags |= _winapi.STARTF_USESTDHANDLES
|
|
71
|
+
startupinfo.hStdInput = p2cread
|
|
72
|
+
startupinfo.hStdOutput = c2pwrite
|
|
73
|
+
startupinfo.hStdError = errwrite
|
|
74
|
+
|
|
75
|
+
attribute_list = startupinfo.lpAttributeList
|
|
76
|
+
have_handle_list = bool(attribute_list and "handle_list" in attribute_list and attribute_list["handle_list"])
|
|
77
|
+
|
|
78
|
+
# If we were given an handle_list or need to create one
|
|
79
|
+
if have_handle_list or (use_std_handles and close_fds):
|
|
80
|
+
if attribute_list is None:
|
|
81
|
+
attribute_list = startupinfo.lpAttributeList = {}
|
|
82
|
+
handle_list = attribute_list["handle_list"] = list(attribute_list.get("handle_list", []))
|
|
83
|
+
|
|
84
|
+
if use_std_handles:
|
|
85
|
+
handle_list += [int(p2cread), int(c2pwrite), int(errwrite)]
|
|
86
|
+
|
|
87
|
+
handle_list[:] = self._filter_handle_list(handle_list)
|
|
88
|
+
|
|
89
|
+
if handle_list:
|
|
90
|
+
if not close_fds:
|
|
91
|
+
warnings.warn("startupinfo.lpAttributeList['handle_list'] overriding close_fds", RuntimeWarning)
|
|
92
|
+
|
|
93
|
+
# When using the handle_list we always request to inherit
|
|
94
|
+
# handles but the only handles that will be inherited are
|
|
95
|
+
# the ones in the handle_list
|
|
96
|
+
close_fds = False
|
|
97
|
+
|
|
98
|
+
assert not shell
|
|
99
|
+
|
|
100
|
+
if cwd is not None:
|
|
101
|
+
cwd = os.fsdecode(cwd)
|
|
102
|
+
|
|
103
|
+
# Start the process
|
|
104
|
+
try:
|
|
105
|
+
hp, ht, pid, tid = _detours.CreateProcessWithDllEx(
|
|
106
|
+
executable,
|
|
107
|
+
args,
|
|
108
|
+
# no special security
|
|
109
|
+
None,
|
|
110
|
+
None,
|
|
111
|
+
not close_fds,
|
|
112
|
+
creationflags,
|
|
113
|
+
env,
|
|
114
|
+
cwd,
|
|
115
|
+
startupinfo,
|
|
116
|
+
dll_name=self.dll_names,
|
|
117
|
+
)
|
|
118
|
+
finally:
|
|
119
|
+
self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite)
|
|
120
|
+
|
|
121
|
+
# Retain the process handle, but close the thread handle
|
|
122
|
+
self._child_created = True
|
|
123
|
+
self._handle = Handle(hp)
|
|
124
|
+
self.pid = pid
|
|
125
|
+
_winapi.CloseHandle(ht)
|
|
7
126
|
|
|
8
127
|
|
|
9
128
|
class WindowsBootstrap(Bootstrap):
|
|
@@ -35,7 +154,7 @@ class WindowsBootstrap(Bootstrap):
|
|
|
35
154
|
env["_NT_SYMBOL_PATH"] = os.pathsep.join(symbol_path_list)
|
|
36
155
|
return env
|
|
37
156
|
|
|
38
|
-
def _add_loopback_exemption(self) ->
|
|
157
|
+
def _add_loopback_exemption(self) -> None:
|
|
39
158
|
sid = "S-1-15-2-1958404141-86561845-1752920682-3514627264-368642714-62675701-733520436"
|
|
40
159
|
ret = subprocess.run(
|
|
41
160
|
["CheckNetIsolation", "LoopbackExempt", "-s", f"-p={sid}"], check=True, capture_output=True
|
|
@@ -44,16 +163,25 @@ class WindowsBootstrap(Bootstrap):
|
|
|
44
163
|
ret = ctypes.windll.shell32.ShellExecuteW(
|
|
45
164
|
None, "runas", "CheckNetIsolation", " ".join(["LoopbackExempt", "-a", f"-p={sid}"]), None, 1
|
|
46
165
|
)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return True
|
|
166
|
+
if ret <= 32:
|
|
167
|
+
raise RuntimeError(f"CheckNetIsolation LoopbackExempt -a failed with exit code {ret}.")
|
|
50
168
|
|
|
51
169
|
def _run(self, *args, **kwargs) -> int:
|
|
52
|
-
|
|
170
|
+
try:
|
|
171
|
+
self._add_loopback_exemption()
|
|
172
|
+
except Exception as e:
|
|
173
|
+
self._logger.warning(
|
|
174
|
+
f"Unable to add loopback exemption: %s. See bedrock_server_how_to.html for more details. {e}"
|
|
175
|
+
)
|
|
53
176
|
|
|
54
|
-
|
|
55
|
-
str(self.executable_path.absolute()),
|
|
56
|
-
|
|
177
|
+
process = PopenWithDll(
|
|
178
|
+
[str(self.executable_path.absolute())],
|
|
179
|
+
text=True,
|
|
180
|
+
encoding="utf-8",
|
|
57
181
|
cwd=str(self.server_path.absolute()),
|
|
58
182
|
env=self._endstone_runtime_env,
|
|
183
|
+
dll_names=str(self._endstone_runtime_path.absolute()),
|
|
184
|
+
*args,
|
|
185
|
+
**kwargs,
|
|
59
186
|
)
|
|
187
|
+
return process.wait()
|
|
Binary file
|