virtualshell 1.2.0__cp314-cp314-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.
- virtualshell/__init__.py +57 -0
- virtualshell/_bootstrap.py +23 -0
- virtualshell/_core.cp314-win_amd64.pyd +0 -0
- virtualshell/_module.py +27 -0
- virtualshell/_protocols.py +214 -0
- virtualshell/_version.py +1 -0
- virtualshell/errors.py +4 -0
- virtualshell/generate_psobject.py +586 -0
- virtualshell/get-session.ps1 +153 -0
- virtualshell/ps_object.py +543 -0
- virtualshell/ps_proxy.py +784 -0
- virtualshell/save-session.ps1 +107 -0
- virtualshell/shell.py +563 -0
- virtualshell/zero_copy_bridge.ps1 +259 -0
- virtualshell/zero_copy_bridge_shell.py +495 -0
- virtualshell-1.2.0.dist-info/DELVEWHEEL +2 -0
- virtualshell-1.2.0.dist-info/METADATA +472 -0
- virtualshell-1.2.0.dist-info/RECORD +21 -0
- virtualshell-1.2.0.dist-info/WHEEL +5 -0
- virtualshell-1.2.0.dist-info/licenses/LICENSE +201 -0
- virtualshell.libs/msvcp140-06f78564ee5e6dd552da1760ee946703.dll +0 -0
virtualshell/__init__.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
# start delvewheel patch
|
|
5
|
+
def _delvewheel_patch_1_13_1():
|
|
6
|
+
import os
|
|
7
|
+
if os.path.isdir(libs_dir := os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, 'virtualshell.libs'))):
|
|
8
|
+
os.add_dll_directory(libs_dir)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
_delvewheel_patch_1_13_1()
|
|
12
|
+
del _delvewheel_patch_1_13_1
|
|
13
|
+
# end delvewheel patch
|
|
14
|
+
|
|
15
|
+
from importlib import import_module
|
|
16
|
+
from typing import TYPE_CHECKING
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from .shell import ExecutionResult, BatchProgress, Shell, ExitCode, Config
|
|
20
|
+
from .zero_copy_bridge_shell import ZeroCopyBridge, PSObject
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
from ._version import version as __version__
|
|
24
|
+
except Exception:
|
|
25
|
+
__version__ = "0.0.0"
|
|
26
|
+
|
|
27
|
+
from .errors import (
|
|
28
|
+
VirtualShellError,
|
|
29
|
+
PowerShellNotFoundError,
|
|
30
|
+
ExecutionTimeoutError,
|
|
31
|
+
ExecutionError,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"VirtualShellError", "PowerShellNotFoundError",
|
|
36
|
+
"ExecutionTimeoutError", "ExecutionError",
|
|
37
|
+
"__version__", "Shell", "ExecutionResult", "BatchProgress", "ExitCode", "Config",
|
|
38
|
+
"ZeroCopyBridge", "PSObject",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
# Lazy loading of submodules and attributes to avoid importing compiled extension at package import time
|
|
42
|
+
def __getattr__(name: str):
|
|
43
|
+
if name in {"Shell", "ExecutionResult", "BatchProgress", "ExitCode", "Config"}:
|
|
44
|
+
mod = import_module(".shell", __name__)
|
|
45
|
+
obj = getattr(mod, name)
|
|
46
|
+
globals()[name] = obj
|
|
47
|
+
return obj
|
|
48
|
+
if name in {"ZeroCopyBridge", "PSObject"}:
|
|
49
|
+
mod = import_module(".zero_copy_bridge_shell", __name__)
|
|
50
|
+
obj = getattr(mod, name)
|
|
51
|
+
globals()[name] = obj
|
|
52
|
+
return obj
|
|
53
|
+
|
|
54
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
55
|
+
|
|
56
|
+
def __dir__():
|
|
57
|
+
return sorted(__all__)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Guarded import of the compiled pybind11 extension.
|
|
2
|
+
|
|
3
|
+
Importing the extension fails if it was never built, or was built for a
|
|
4
|
+
different Python version or platform. Every import of it is funnelled
|
|
5
|
+
through here so that failure surfaces as a single, actionable ImportError
|
|
6
|
+
instead of a bare ``ModuleNotFoundError``.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import importlib
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
_CORE_MODULE_NAME = f"{__package__}._core"
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
core: Any = importlib.import_module(_CORE_MODULE_NAME)
|
|
19
|
+
except Exception as e:
|
|
20
|
+
raise ImportError(
|
|
21
|
+
f"Failed to import the compiled extension '{_CORE_MODULE_NAME}'. "
|
|
22
|
+
"Make sure it was built and matches this Python/platform."
|
|
23
|
+
) from e
|
|
Binary file
|
virtualshell/_module.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import importlib
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
_CORE_MODULE_NAME = f"{__package__}._core"
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
core = importlib.import_module(_CORE_MODULE_NAME)
|
|
10
|
+
except Exception as e:
|
|
11
|
+
raise ImportError(
|
|
12
|
+
f"Failed to import the compiled extension '{_CORE_MODULE_NAME}'. "
|
|
13
|
+
"Make sure it was built and matches this Python/platform."
|
|
14
|
+
) from e
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from ._protocols import (
|
|
18
|
+
ExecutionResultLike as ExecutionResult,
|
|
19
|
+
BatchProgressLike as BatchProgress,
|
|
20
|
+
ConfigLike as Config,
|
|
21
|
+
VirtualShellLike as VirtualShell,
|
|
22
|
+
)
|
|
23
|
+
else:
|
|
24
|
+
ExecutionResult = core.ExecutionResult
|
|
25
|
+
BatchProgress = core.BatchProgress
|
|
26
|
+
Config = core.Config
|
|
27
|
+
VirtualShell = core.VirtualShell
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from enum import IntEnum
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
from typing import (
|
|
7
|
+
Protocol,
|
|
8
|
+
Any,
|
|
9
|
+
Callable,
|
|
10
|
+
List,
|
|
11
|
+
Dict,
|
|
12
|
+
Self,
|
|
13
|
+
runtime_checkable,
|
|
14
|
+
)
|
|
15
|
+
from concurrent.futures import Future
|
|
16
|
+
|
|
17
|
+
class ExitCode(IntEnum):
|
|
18
|
+
SUCCESS = 0
|
|
19
|
+
GENERAL_ERROR = 1
|
|
20
|
+
TIMEOUT = -1
|
|
21
|
+
RESTARTING = -2 # Internal use; not from PowerShell itself.
|
|
22
|
+
NOT_RUNNING = -3 # Internal use; not from PowerShell itself.
|
|
23
|
+
|
|
24
|
+
@runtime_checkable
|
|
25
|
+
class ExecutionResultLike(Protocol):
|
|
26
|
+
out: Any
|
|
27
|
+
err: Any
|
|
28
|
+
exit_code: ExitCode
|
|
29
|
+
success: bool
|
|
30
|
+
execution_time: float
|
|
31
|
+
|
|
32
|
+
@runtime_checkable
|
|
33
|
+
class BatchProgressLike(Protocol):
|
|
34
|
+
currentCommand: int
|
|
35
|
+
totalCommands: int
|
|
36
|
+
lastResult: ExecutionResultLike
|
|
37
|
+
isComplete: bool
|
|
38
|
+
allResults: List[ExecutionResultLike]
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def header_bytes(self) -> int: ...
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def frame_bytes(self) -> int: ...
|
|
45
|
+
|
|
46
|
+
def __init__(self) -> None:
|
|
47
|
+
...
|
|
48
|
+
|
|
49
|
+
@runtime_checkable
|
|
50
|
+
class ConfigLike(Protocol):
|
|
51
|
+
powershell_path: str = "pwsh"
|
|
52
|
+
working_directory: str = ""
|
|
53
|
+
capture_output: bool = True
|
|
54
|
+
capture_error: bool = True
|
|
55
|
+
auto_restart_on_timeout: bool = True
|
|
56
|
+
timeout_seconds: int = 30
|
|
57
|
+
environment: dict[str, str]
|
|
58
|
+
initial_commands: List[str]
|
|
59
|
+
restore_script_path: str = ""
|
|
60
|
+
session_snapshot_path: str = ""
|
|
61
|
+
stdin_buffer_size: int = 64 * 1024
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def __init__(self) -> None:
|
|
65
|
+
...
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@runtime_checkable
|
|
69
|
+
class VirtualShellLike(Protocol):
|
|
70
|
+
|
|
71
|
+
# ---------------------------------------------------------
|
|
72
|
+
# Process control
|
|
73
|
+
# ---------------------------------------------------------
|
|
74
|
+
def start(self) -> bool:
|
|
75
|
+
...
|
|
76
|
+
|
|
77
|
+
def stop(self, force: bool = False) -> None:
|
|
78
|
+
...
|
|
79
|
+
|
|
80
|
+
def is_alive(self) -> bool:
|
|
81
|
+
...
|
|
82
|
+
|
|
83
|
+
def is_restarting(self) -> bool:
|
|
84
|
+
...
|
|
85
|
+
|
|
86
|
+
def get_process_id(self) -> int:
|
|
87
|
+
...
|
|
88
|
+
|
|
89
|
+
# ---------------------------------------------------------
|
|
90
|
+
# Sync commands
|
|
91
|
+
# ---------------------------------------------------------
|
|
92
|
+
def execute(self, command: str, timeout_seconds: float = 0.0) -> ExecutionResultLike:
|
|
93
|
+
...
|
|
94
|
+
|
|
95
|
+
def execute_batch(self, commands: List[str], timeout_seconds: float = 0.0) -> List[ExecutionResultLike]:
|
|
96
|
+
...
|
|
97
|
+
|
|
98
|
+
def execute_script(
|
|
99
|
+
self,
|
|
100
|
+
script_path: str,
|
|
101
|
+
args: List[str] = ...,
|
|
102
|
+
timeout_seconds: float = 0.0,
|
|
103
|
+
dot_source: bool = False,
|
|
104
|
+
raise_on_error: bool = False
|
|
105
|
+
) -> ExecutionResultLike:
|
|
106
|
+
...
|
|
107
|
+
|
|
108
|
+
def execute_script_kv(
|
|
109
|
+
self,
|
|
110
|
+
script_path: str,
|
|
111
|
+
named_args: Dict[str, str],
|
|
112
|
+
timeout_seconds: float = 0.0,
|
|
113
|
+
dot_source: bool = False,
|
|
114
|
+
raise_on_error: bool = False
|
|
115
|
+
) -> ExecutionResultLike:
|
|
116
|
+
...
|
|
117
|
+
|
|
118
|
+
# ---------------------------------------------------------
|
|
119
|
+
# Async commands
|
|
120
|
+
# ---------------------------------------------------------
|
|
121
|
+
def execute_async(
|
|
122
|
+
self,
|
|
123
|
+
command: str,
|
|
124
|
+
callback: Callable[..., Any] | None = None,
|
|
125
|
+
timeout_seconds: float = 0.0
|
|
126
|
+
) -> Future[ExecutionResultLike]:
|
|
127
|
+
...
|
|
128
|
+
|
|
129
|
+
def execute_async_batch(
|
|
130
|
+
self,
|
|
131
|
+
commands: List[str],
|
|
132
|
+
progress_callback: Callable[..., Any] | None = None,
|
|
133
|
+
stop_on_first_error: bool = True,
|
|
134
|
+
per_command_timeout_seconds: float = 0.0
|
|
135
|
+
) -> Future[List[ExecutionResultLike]]:
|
|
136
|
+
...
|
|
137
|
+
|
|
138
|
+
def execute_async_script(
|
|
139
|
+
self,
|
|
140
|
+
script_path: str,
|
|
141
|
+
args: List[str] = ...,
|
|
142
|
+
callback: Callable[..., Any] | None = None,
|
|
143
|
+
timeout_seconds: float = 0.0,
|
|
144
|
+
dot_source: bool = False,
|
|
145
|
+
raise_on_error: bool = False
|
|
146
|
+
) -> Future[ExecutionResultLike]:
|
|
147
|
+
...
|
|
148
|
+
|
|
149
|
+
def execute_async_script_kv(
|
|
150
|
+
self,
|
|
151
|
+
script_path: str,
|
|
152
|
+
named_args: Dict[str, str],
|
|
153
|
+
timeout_seconds: float = 0.0,
|
|
154
|
+
dot_source: bool = False,
|
|
155
|
+
raise_on_error: bool = False
|
|
156
|
+
) -> Future[ExecutionResultLike]:
|
|
157
|
+
...
|
|
158
|
+
|
|
159
|
+
# ---------------------------------------------------------
|
|
160
|
+
# Direct I/O / env / modules
|
|
161
|
+
# ---------------------------------------------------------
|
|
162
|
+
def send_input(self, input: str) -> bool:
|
|
163
|
+
...
|
|
164
|
+
|
|
165
|
+
def read_output(self, blocking: bool = False) -> str:
|
|
166
|
+
...
|
|
167
|
+
|
|
168
|
+
def read_error(self, blocking: bool = False) -> str:
|
|
169
|
+
...
|
|
170
|
+
|
|
171
|
+
def set_working_directory(self, directory: str) -> bool:
|
|
172
|
+
...
|
|
173
|
+
|
|
174
|
+
def get_working_directory(self) -> str:
|
|
175
|
+
...
|
|
176
|
+
|
|
177
|
+
def set_environment_variable(self, name: str, value: str) -> bool:
|
|
178
|
+
...
|
|
179
|
+
|
|
180
|
+
def get_environment_variable(self, name: str) -> str:
|
|
181
|
+
...
|
|
182
|
+
|
|
183
|
+
def is_module_available(self, module_name: str) -> bool:
|
|
184
|
+
...
|
|
185
|
+
|
|
186
|
+
def import_module(self, module_name: str) -> bool:
|
|
187
|
+
...
|
|
188
|
+
|
|
189
|
+
def get_powershell_version(self) -> str:
|
|
190
|
+
...
|
|
191
|
+
|
|
192
|
+
def get_available_modules(self) -> List[str]:
|
|
193
|
+
...
|
|
194
|
+
|
|
195
|
+
# ---------------------------------------------------------
|
|
196
|
+
# Configuration and Internals
|
|
197
|
+
# ---------------------------------------------------------
|
|
198
|
+
def get_config(self) -> ConfigLike:
|
|
199
|
+
...
|
|
200
|
+
|
|
201
|
+
def update_config(self, config: ConfigLike) -> bool:
|
|
202
|
+
...
|
|
203
|
+
|
|
204
|
+
def get_shared_ptr(self) -> Self:
|
|
205
|
+
...
|
|
206
|
+
|
|
207
|
+
# ---------------------------------------------------------
|
|
208
|
+
# Context Manager
|
|
209
|
+
# ---------------------------------------------------------
|
|
210
|
+
def __enter__(self) -> "VirtualShellLike":
|
|
211
|
+
...
|
|
212
|
+
|
|
213
|
+
def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
|
214
|
+
...
|
virtualshell/_version.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
version = "1.2.0"
|
virtualshell/errors.py
ADDED