virtualshell 1.1.6__tar.gz → 1.2.1__tar.gz
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-1.1.6 → virtualshell-1.2.1}/.github/workflows/test_build-only.yml +4 -3
- {virtualshell-1.1.6 → virtualshell-1.2.1}/.github/workflows/workflow.yml +11 -22
- {virtualshell-1.1.6 → virtualshell-1.2.1}/.gitignore +3 -1
- {virtualshell-1.1.6 → virtualshell-1.2.1}/CMakeLists.txt +14 -32
- {virtualshell-1.1.6 → virtualshell-1.2.1}/PKG-INFO +128 -119
- virtualshell-1.2.1/README.md +257 -0
- virtualshell-1.2.1/bench/bench.csv +4 -0
- virtualshell-1.2.1/bench/bench.json +440 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/bench/vs_bench.py +3 -6
- virtualshell-1.2.1/bench/zcb_bench.json +69 -0
- virtualshell-1.2.1/bench/zcb_bench.py +153 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/include/cmd_state.hpp +1 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/src/binder.cpp +103 -115
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/src/powershell_process.cpp +64 -2
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/src/virtual_shell.cpp +29 -3
- virtualshell-1.2.1/cpp/tests/CMakeLists.txt +26 -0
- virtualshell-1.2.1/cpp/tests/test_framework.hpp +116 -0
- virtualshell-1.2.1/cpp/tests/test_helpers.cpp +126 -0
- virtualshell-1.2.1/cpp/tests/test_main.cpp +5 -0
- virtualshell-1.2.1/cpp/tests/test_virtual_shell.cpp +271 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/pyproject.toml +12 -4
- virtualshell-1.2.1/src/virtualshell/__init__.py +44 -0
- virtualshell-1.2.1/src/virtualshell/_bootstrap.py +23 -0
- virtualshell-1.2.1/src/virtualshell/_module.py +27 -0
- virtualshell-1.2.1/src/virtualshell/_protocols.py +214 -0
- virtualshell-1.2.1/src/virtualshell/_version.py +1 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/src/virtualshell/generate_psobject.py +268 -162
- virtualshell-1.2.1/src/virtualshell/ps_object.py +543 -0
- virtualshell-1.2.1/src/virtualshell/ps_proxy.py +949 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/src/virtualshell/shell.py +102 -73
- virtualshell-1.2.1/src/virtualshell/zero_copy_bridge.ps1 +259 -0
- virtualshell-1.2.1/src/virtualshell/zero_copy_bridge_shell.py +495 -0
- virtualshell-1.2.1/tests/conftest.py +231 -0
- virtualshell-1.2.1/tests/test_generate_psobject.py +436 -0
- virtualshell-1.2.1/tests/test_integration.py +175 -0
- virtualshell-1.2.1/tests/test_ps_proxy_integration.py +397 -0
- virtualshell-1.2.1/tests/test_ps_proxy_unit.py +213 -0
- virtualshell-1.2.1/tests/test_psobject_unit.py +155 -0
- virtualshell-1.2.1/tests/test_shell_unit.py +369 -0
- virtualshell-1.2.1/tests/test_utils_unit.py +113 -0
- virtualshell-1.2.1/tests/test_zcb_channel_unit.py +206 -0
- virtualshell-1.2.1/tests/test_zcb_integration.py +170 -0
- virtualshell-1.2.1/wiki/Project/Benchmarks.md +83 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Usage/API Overview.md +2 -1
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Usage/Zero-Copy Bridge.md +23 -9
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Usage/generate_psobject.md +29 -5
- virtualshell-1.2.1/wiki/Usage/make_proxy.md +203 -0
- virtualshell-1.1.6/README.md +0 -253
- virtualshell-1.1.6/bench/bench.csv +0 -4
- virtualshell-1.1.6/bench/bench.json +0 -435
- virtualshell-1.1.6/cpp/include/py_proxy.hpp +0 -76
- virtualshell-1.1.6/cpp/lib/vs_shm/CMakeLists.txt +0 -92
- virtualshell-1.1.6/cpp/lib/vs_shm/include/vs_shm.h +0 -237
- virtualshell-1.1.6/cpp/lib/vs_shm/src/object_serializer.cpp +0 -215
- virtualshell-1.1.6/cpp/lib/vs_shm/src/vs_shm.cpp +0 -514
- virtualshell-1.1.6/cpp/src/py_proxy.cpp +0 -1292
- virtualshell-1.1.6/src/virtualshell/__init__.py +0 -57
- virtualshell-1.1.6/src/virtualshell/_globals.py +0 -11
- virtualshell-1.1.6/src/virtualshell/_version.py +0 -1
- virtualshell-1.1.6/src/virtualshell/zero_copy_bridge.ps1 +0 -584
- virtualshell-1.1.6/src/virtualshell/zero_copy_bridge_shell.py +0 -1054
- virtualshell-1.1.6/wiki/Project/Benchmarks.md +0 -65
- virtualshell-1.1.6/wiki/Usage/make_proxy.md +0 -124
- {virtualshell-1.1.6 → virtualshell-1.2.1}/CMakeSettings.json +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/LICENSE +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/include/config.hpp +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/include/dev_debug.hpp +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/include/execution_result.hpp +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/include/helpers.hpp +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/include/io_pump.hpp +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/include/powershell_process.hpp +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/include/process.hpp +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/include/py_bridge.hpp +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/include/timeout_watcher.hpp +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/include/virtual_shell.hpp +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/cpp/src/io_pump.cpp +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/src/virtualshell/errors.py +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/src/virtualshell/get-session.ps1 +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/src/virtualshell/save-session.ps1 +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Getting started/Getting started.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Getting started/Installation.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Getting started/Quickstart.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Help/FAQ.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Help/Troubleshooting.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Home.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Project/Changelog.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Project/Design & Architecture.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Usage/Asynchronous Execution.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Usage/Configuration.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Usage/Error Handling.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Usage/Performance Tips.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Usage/Running Scripts.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Usage/Security Notes.md +0 -0
- {virtualshell-1.1.6 → virtualshell-1.2.1}/wiki/Usage/Synchronous Execution.md +0 -0
|
@@ -199,10 +199,11 @@ jobs:
|
|
|
199
199
|
CIBW_SKIP: "*-win32"
|
|
200
200
|
CIBW_TEST_COMMAND: python -c "import virtualshell; print('ok')"
|
|
201
201
|
CIBW_BUILD_VERBOSITY: "1"
|
|
202
|
+
# Ninja is forced by pyproject (cmake.args); the compiler comes from
|
|
203
|
+
# the VsDevCmd environment set up below, whatever VS version the
|
|
204
|
+
# runner image ships.
|
|
202
205
|
CIBW_ENVIRONMENT_WINDOWS: >
|
|
203
|
-
CMAKE_GENERATOR=
|
|
204
|
-
CMAKE_GENERATOR_PLATFORM=x64
|
|
205
|
-
SKBUILD_CMAKE_GENERATOR="Visual Studio 17 2022"
|
|
206
|
+
CMAKE_GENERATOR=Ninja
|
|
206
207
|
PYBIND11_FINDPYTHON=ON
|
|
207
208
|
CMAKE_BUILD_TYPE=Release
|
|
208
209
|
run: |
|
|
@@ -25,18 +25,14 @@ jobs:
|
|
|
25
25
|
fail-fast: false
|
|
26
26
|
matrix:
|
|
27
27
|
include:
|
|
28
|
-
- python: "cp38-*"
|
|
29
|
-
label: "cp38"
|
|
30
|
-
- python: "cp39-*"
|
|
31
|
-
label: "cp39"
|
|
32
|
-
- python: "cp310-*"
|
|
33
|
-
label: "cp310"
|
|
34
28
|
- python: "cp311-*"
|
|
35
29
|
label: "cp311"
|
|
36
30
|
- python: "cp312-*"
|
|
37
31
|
label: "cp312"
|
|
38
32
|
- python: "cp313-*"
|
|
39
33
|
label: "cp313"
|
|
34
|
+
- python: "cp314-*"
|
|
35
|
+
label: "cp314"
|
|
40
36
|
steps:
|
|
41
37
|
- uses: actions/checkout@v4
|
|
42
38
|
with:
|
|
@@ -80,18 +76,14 @@ jobs:
|
|
|
80
76
|
fail-fast: false
|
|
81
77
|
matrix:
|
|
82
78
|
include:
|
|
83
|
-
- python: "cp38-*"
|
|
84
|
-
label: "cp38"
|
|
85
|
-
- python: "cp39-*"
|
|
86
|
-
label: "cp39"
|
|
87
|
-
- python: "cp310-*"
|
|
88
|
-
label: "cp310"
|
|
89
79
|
- python: "cp311-*"
|
|
90
80
|
label: "cp311"
|
|
91
81
|
- python: "cp312-*"
|
|
92
82
|
label: "cp312"
|
|
93
83
|
- python: "cp313-*"
|
|
94
84
|
label: "cp313"
|
|
85
|
+
- python: "cp314-*"
|
|
86
|
+
label: "cp314"
|
|
95
87
|
steps:
|
|
96
88
|
- uses: actions/checkout@v4
|
|
97
89
|
with:
|
|
@@ -139,18 +131,14 @@ jobs:
|
|
|
139
131
|
fail-fast: false
|
|
140
132
|
matrix:
|
|
141
133
|
include:
|
|
142
|
-
- python: "cp38-*"
|
|
143
|
-
label: "cp38"
|
|
144
|
-
- python: "cp39-*"
|
|
145
|
-
label: "cp39"
|
|
146
|
-
- python: "cp310-*"
|
|
147
|
-
label: "cp310"
|
|
148
134
|
- python: "cp311-*"
|
|
149
135
|
label: "cp311"
|
|
150
136
|
- python: "cp312-*"
|
|
151
137
|
label: "cp312"
|
|
152
138
|
- python: "cp313-*"
|
|
153
139
|
label: "cp313"
|
|
140
|
+
- python: "cp314-*"
|
|
141
|
+
label: "cp314"
|
|
154
142
|
|
|
155
143
|
steps:
|
|
156
144
|
- uses: actions/checkout@v4
|
|
@@ -203,7 +191,7 @@ jobs:
|
|
|
203
191
|
strategy:
|
|
204
192
|
fail-fast: false
|
|
205
193
|
matrix:
|
|
206
|
-
python: ["
|
|
194
|
+
python: ["cp311-win_amd64", "cp312-win_amd64", "cp313-win_amd64", "cp314-win_amd64"]
|
|
207
195
|
|
|
208
196
|
steps:
|
|
209
197
|
- uses: actions/checkout@v4
|
|
@@ -228,10 +216,11 @@ jobs:
|
|
|
228
216
|
CIBW_SKIP: "*-win32"
|
|
229
217
|
CIBW_TEST_COMMAND: python -c "import virtualshell; print('ok')"
|
|
230
218
|
CIBW_BUILD_VERBOSITY: "1"
|
|
219
|
+
# Ninja is forced by pyproject (cmake.args); the compiler comes from
|
|
220
|
+
# the VsDevCmd environment set up below, whatever VS version the
|
|
221
|
+
# runner image ships.
|
|
231
222
|
CIBW_ENVIRONMENT_WINDOWS: >
|
|
232
|
-
CMAKE_GENERATOR=
|
|
233
|
-
CMAKE_GENERATOR_PLATFORM=x64
|
|
234
|
-
SKBUILD_CMAKE_GENERATOR="Visual Studio 17 2022"
|
|
223
|
+
CMAKE_GENERATOR=Ninja
|
|
235
224
|
PYBIND11_FINDPYTHON=ON
|
|
236
225
|
CMAKE_BUILD_TYPE=Release
|
|
237
226
|
run: |
|
|
@@ -39,7 +39,6 @@ set(SRC
|
|
|
39
39
|
cpp/src/io_pump.cpp
|
|
40
40
|
cpp/src/powershell_process.cpp
|
|
41
41
|
cpp/src/virtual_shell.cpp
|
|
42
|
-
cpp/src/py_proxy.cpp
|
|
43
42
|
)
|
|
44
43
|
|
|
45
44
|
file(GLOB_RECURSE VS_HEADERS CONFIGURE_DEPENDS
|
|
@@ -47,7 +46,15 @@ file(GLOB_RECURSE VS_HEADERS CONFIGURE_DEPENDS
|
|
|
47
46
|
"${CMAKE_CURRENT_SOURCE_DIR}/cpp/include/*.hpp"
|
|
48
47
|
)
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
# NO_EXTRAS on MSVC: pybind11's default /GL + LTCG (whole-program optimization)
|
|
50
|
+
# triggers an internal compiler error (C1001) in newer MSVC toolsets
|
|
51
|
+
# (observed with VS 2026 / cl 19.51) on the binder's lambda templates.
|
|
52
|
+
# The binding layer is I/O-bound, so LTO buys nothing here anyway.
|
|
53
|
+
if(MSVC)
|
|
54
|
+
pybind11_add_module(_core MODULE NO_EXTRAS ${SRC} ${VS_HEADERS})
|
|
55
|
+
else()
|
|
56
|
+
pybind11_add_module(_core MODULE ${SRC} ${VS_HEADERS})
|
|
57
|
+
endif()
|
|
51
58
|
target_include_directories(_core PRIVATE cpp/include)
|
|
52
59
|
|
|
53
60
|
# Link platform-specific libraries
|
|
@@ -93,36 +100,11 @@ install(TARGETS _core
|
|
|
93
100
|
ARCHIVE DESTINATION virtualshell
|
|
94
101
|
)
|
|
95
102
|
|
|
96
|
-
#
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
RUNTIME_OUTPUT_DIRECTORY "${_VS_OUTDIR}"
|
|
102
|
-
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${_VS_OUTDIR}"
|
|
103
|
-
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${_VS_OUTDIR}"
|
|
104
|
-
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${_VS_OUTDIR}"
|
|
105
|
-
LIBRARY_OUTPUT_DIRECTORY "${_VS_OUTDIR}"
|
|
106
|
-
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${_VS_OUTDIR}"
|
|
107
|
-
LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${_VS_OUTDIR}"
|
|
108
|
-
LIBRARY_OUTPUT_DIRECTORY_DEBUG "${_VS_OUTDIR}"
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
add_dependencies(_core _vs_shm)
|
|
112
|
-
|
|
113
|
-
add_custom_command(TARGET _core POST_BUILD
|
|
114
|
-
COMMAND ${CMAKE_COMMAND} -E make_directory "${_VS_OUTDIR}"
|
|
115
|
-
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
116
|
-
"$<TARGET_FILE:_vs_shm>"
|
|
117
|
-
"${_VS_OUTDIR}/$<TARGET_FILE_NAME:_vs_shm>"
|
|
118
|
-
VERBATIM
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
install(TARGETS _vs_shm
|
|
122
|
-
RUNTIME DESTINATION virtualshell
|
|
123
|
-
LIBRARY DESTINATION virtualshell
|
|
124
|
-
ARCHIVE DESTINATION virtualshell
|
|
125
|
-
)
|
|
103
|
+
# C++ tests (opt-in; never built by pip/scikit-build)
|
|
104
|
+
option(VIRTUALSHELL_BUILD_TESTS "Build the C++ test suite (vs_core_tests)" OFF)
|
|
105
|
+
if(VIRTUALSHELL_BUILD_TESTS)
|
|
106
|
+
enable_testing()
|
|
107
|
+
add_subdirectory(cpp/tests)
|
|
126
108
|
endif()
|
|
127
109
|
|
|
128
110
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: virtualshell
|
|
3
|
-
Version: 1.1
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: High-performance PowerShell bridge (C++ pybind11 backend)
|
|
5
5
|
Keywords: powershell,automation,shell,cpp,pybind11
|
|
6
6
|
Author: Kim-Andre Myrvold
|
|
@@ -208,105 +208,90 @@ License: Apache License
|
|
|
208
208
|
|
|
209
209
|
Classifier: Programming Language :: Python :: 3
|
|
210
210
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
211
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
212
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
213
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
214
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
211
215
|
Classifier: Programming Language :: C++
|
|
212
216
|
Classifier: Operating System :: Microsoft :: Windows
|
|
213
217
|
Classifier: Operating System :: POSIX :: Linux
|
|
218
|
+
Classifier: Operating System :: MacOS
|
|
214
219
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
215
220
|
Project-URL: Homepage, https://github.com/Chamoswor/virtualshell
|
|
216
221
|
Project-URL: Issues, https://github.com/Chamoswor/virtualshell/issues
|
|
217
|
-
Requires-Python: >=3.
|
|
222
|
+
Requires-Python: >=3.11
|
|
218
223
|
Description-Content-Type: text/markdown
|
|
219
224
|
|
|
220
|
-
#
|
|
225
|
+
# virtualshell
|
|
226
|
+
|
|
221
227
|
[](https://pypi.org/project/virtualshell/)
|
|
222
228
|
[](https://pypi.org/project/virtualshell/)
|
|
223
229
|
[](#)
|
|
224
230
|
[](LICENSE)
|
|
225
231
|
[](https://github.com/Chamoswor/virtualshell/actions)
|
|
226
232
|
|
|
233
|
+
**High-performance PowerShell automation for Python.**
|
|
234
|
+
Run PowerShell commands with millisecond latency, persistent sessions, async
|
|
235
|
+
execution, and a cross-platform zero-copy bridge — without juggling
|
|
236
|
+
subprocesses.
|
|
227
237
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
> 🔗 **Full documentation lives in the [wiki](https://github.com/Chamoswor/virtualshell/wiki)**
|
|
232
|
-
> This README focuses on *what it is*, *why it matters*, and *how to get started fast*.
|
|
233
|
-
|
|
234
|
-
## ✨ What is virtualshell?
|
|
235
|
-
|
|
236
|
-
`virtualshell` keeps **one PowerShell host warm** behind a thin Python wrapper powered by a **C++ engine**.
|
|
237
|
-
|
|
238
|
-
Instead of spawning `pwsh` for every command, you get:
|
|
239
|
-
|
|
240
|
-
* a **persistent PowerShell session**
|
|
241
|
-
* **~2–4 ms execution latency**
|
|
242
|
-
* **async + batch execution**
|
|
243
|
-
* **structured, predictable results**
|
|
244
|
-
* optional **zero-copy shared memory** (Windows)
|
|
245
|
-
|
|
246
|
-
Perfect for:
|
|
247
|
-
|
|
248
|
-
* Python orchestration layers
|
|
249
|
-
* long-running agents
|
|
250
|
-
* CI/test harnesses
|
|
251
|
-
* automation tooling that must be *fast and reliable*
|
|
252
|
-
|
|
253
|
-
## 🚀 Why use it?
|
|
238
|
+
Full documentation lives in the
|
|
239
|
+
[wiki](https://github.com/Chamoswor/virtualshell/wiki). This README covers
|
|
240
|
+
what the library is, why it matters, and how to get started.
|
|
254
241
|
|
|
255
|
-
|
|
256
|
-
Reuse loaded modules, `$env:*`, functions, and global state.
|
|
242
|
+
## What is virtualshell?
|
|
257
243
|
|
|
258
|
-
|
|
259
|
-
|
|
244
|
+
`virtualshell` keeps one PowerShell host warm behind a thin Python wrapper
|
|
245
|
+
powered by a C++ engine. Instead of spawning `pwsh` for every command, you
|
|
246
|
+
get:
|
|
260
247
|
|
|
261
|
-
*
|
|
262
|
-
|
|
248
|
+
* a persistent PowerShell session
|
|
249
|
+
* ~2–4 ms execution latency
|
|
250
|
+
* async and batch execution
|
|
251
|
+
* structured, predictable results
|
|
252
|
+
* optional zero-copy shared memory transfers (cross-platform)
|
|
253
|
+
* live object proxies with generated type stubs
|
|
263
254
|
|
|
264
|
-
|
|
265
|
-
|
|
255
|
+
Typical use cases include Python orchestration layers, long-running agents,
|
|
256
|
+
CI/test harnesses, and automation tooling that must be fast and reliable.
|
|
266
257
|
|
|
267
|
-
|
|
268
|
-
Typed Python exceptions for timeouts, missing PowerShell, execution errors.
|
|
258
|
+
## Why use it?
|
|
269
259
|
|
|
270
|
-
*
|
|
271
|
-
|
|
260
|
+
* **Persistent session** — reuse loaded modules, `$env:*`, functions, and
|
|
261
|
+
global state across calls.
|
|
262
|
+
* **Low latency** — avoid the ~200 ms cost of `subprocess.run("pwsh")` per
|
|
263
|
+
command.
|
|
264
|
+
* **Async and batching** — schedule concurrent commands with timeouts and
|
|
265
|
+
callbacks.
|
|
266
|
+
* **Structured results** — every call returns stdout, stderr, exit code,
|
|
267
|
+
timing, and success state.
|
|
268
|
+
* **Predictable failures** — typed Python exceptions for timeouts, missing
|
|
269
|
+
PowerShell, and execution errors.
|
|
270
|
+
* **Type-safe automation** — generate Python `Protocol` stubs from
|
|
271
|
+
PowerShell objects and control them through live proxies.
|
|
272
272
|
|
|
273
|
-
##
|
|
273
|
+
## Requirements
|
|
274
274
|
|
|
275
|
-
|
|
275
|
+
* **Python 3.11 – 3.14**
|
|
276
|
+
* **PowerShell 7** (`pwsh`) on `PATH`, unless an explicit path is passed in
|
|
277
|
+
the configuration
|
|
276
278
|
|
|
277
|
-
|
|
278
|
-
* **Linux** (x86_64 / aarch64)
|
|
279
|
-
* **macOS** (universal2)
|
|
279
|
+
## Installation
|
|
280
280
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
PowerShell (`pwsh` or `powershell.exe`) must be available on `PATH`,
|
|
284
|
-
unless you pass an explicit path in the configuration.
|
|
285
|
-
|
|
286
|
-
---
|
|
287
|
-
|
|
288
|
-
### ✅ Recommended: install pre-built wheels
|
|
281
|
+
Pre-built wheels are published for Windows (x64), Linux (x86_64 / aarch64),
|
|
282
|
+
and macOS (universal2):
|
|
289
283
|
|
|
290
284
|
```bash
|
|
291
285
|
pip install virtualshell
|
|
292
286
|
```
|
|
293
287
|
|
|
294
|
-
No compiler or build tools required.
|
|
295
|
-
|
|
296
|
-
---
|
|
297
|
-
|
|
298
|
-
### 🔧 Build from source (optional)
|
|
288
|
+
No compiler or build tools are required when installing wheels.
|
|
299
289
|
|
|
300
|
-
|
|
290
|
+
### Building from source (optional)
|
|
301
291
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
* Workload: *Desktop development with C++*
|
|
307
|
-
2. Open **x64 Native Tools Command Prompt for VS**
|
|
308
|
-
|
|
309
|
-
---
|
|
292
|
+
Building locally requires CMake and a C++17 compiler. On Windows, install
|
|
293
|
+
Visual Studio Build Tools with the *Desktop development with C++* workload
|
|
294
|
+
and run the build from an *x64 Native Tools Command Prompt* (64-bit only).
|
|
310
295
|
|
|
311
296
|
```bash
|
|
312
297
|
pip install virtualshell --no-binary virtualshell
|
|
@@ -318,17 +303,13 @@ Or directly from GitHub:
|
|
|
318
303
|
pip install "git+https://github.com/Chamoswor/virtualshell"
|
|
319
304
|
```
|
|
320
305
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
### 🔍 Verify installation
|
|
306
|
+
Verify the installation:
|
|
324
307
|
|
|
325
308
|
```bash
|
|
326
309
|
python -c "import virtualshell; print('virtualshell OK')"
|
|
327
310
|
```
|
|
328
311
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
## ⚡ Quick start
|
|
312
|
+
## Quick start
|
|
332
313
|
|
|
333
314
|
```python
|
|
334
315
|
from virtualshell import Shell
|
|
@@ -371,19 +352,18 @@ shell.script(Path("test.ps1"), args={"Name": "Alice", "Count": "3"})
|
|
|
371
352
|
shell.stop()
|
|
372
353
|
```
|
|
373
354
|
|
|
374
|
-
All execution APIs support
|
|
375
|
-
|
|
376
|
-
* per-call timeouts
|
|
377
|
-
* `raise_on_error`
|
|
378
|
-
* callbacks
|
|
379
|
-
|
|
380
|
-
## 🧠 Advanced features
|
|
355
|
+
All execution APIs support per-call timeouts, `raise_on_error`, and
|
|
356
|
+
callbacks.
|
|
381
357
|
|
|
382
|
-
|
|
358
|
+
## Advanced features
|
|
383
359
|
|
|
384
|
-
|
|
360
|
+
### Zero-copy bridge
|
|
385
361
|
|
|
386
|
-
|
|
362
|
+
High-throughput shared-memory transfer between Python and PowerShell, suited
|
|
363
|
+
for large binary blobs, files, or high-frequency data exchange. The payload
|
|
364
|
+
moves through a file-backed memory map shared between Python (`mmap`) and
|
|
365
|
+
PowerShell (.NET `MemoryMappedFile`) — no native DLL required, on Windows,
|
|
366
|
+
Linux, and macOS.
|
|
387
367
|
|
|
388
368
|
```python
|
|
389
369
|
from virtualshell import Shell, ZeroCopyBridge
|
|
@@ -391,50 +371,66 @@ from virtualshell import Shell, ZeroCopyBridge
|
|
|
391
371
|
with Shell(timeout_seconds=60) as shell:
|
|
392
372
|
with ZeroCopyBridge(shell) as bridge:
|
|
393
373
|
data = b"x" * 1_000_000
|
|
394
|
-
bridge.send(data, "
|
|
374
|
+
bridge.send(data, "buf")
|
|
395
375
|
print(shell.run("$buf.Length").out)
|
|
396
376
|
```
|
|
397
377
|
|
|
398
|
-
|
|
399
|
-
|
|
378
|
+
Measured throughput is roughly 145–560 MB/s depending on payload size and
|
|
379
|
+
direction — about 10–40× faster than piping the same data through stdout as
|
|
380
|
+
base64. See the wiki for the full guide, including `PSObject` round-trips
|
|
381
|
+
between Python and PowerShell.
|
|
400
382
|
|
|
401
|
-
|
|
383
|
+
### PowerShell object proxies
|
|
402
384
|
|
|
403
|
-
|
|
385
|
+
Control live .NET/PowerShell objects from Python. Scalars convert to native
|
|
386
|
+
Python types, byte arrays travel through the zero-copy bridge, and complex
|
|
387
|
+
values come back as sub-proxies.
|
|
404
388
|
|
|
405
|
-
|
|
389
|
+
```python
|
|
390
|
+
with Shell() as sh:
|
|
391
|
+
writer = sh.make_proxy("", "System.IO.StreamWriter('test.txt')")
|
|
392
|
+
writer.WriteLine("Hello")
|
|
393
|
+
writer.Close()
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
A bare `[Type]` literal binds the type itself, exposing its **static**
|
|
397
|
+
methods, properties and constants:
|
|
406
398
|
|
|
407
399
|
```python
|
|
408
|
-
|
|
409
|
-
"
|
|
410
|
-
|
|
411
|
-
|
|
400
|
+
with Shell() as sh:
|
|
401
|
+
math = sh.make_proxy("", "[System.Math]")
|
|
402
|
+
print(math.Sqrt(16.0), math.PI) # 4.0 3.141592653589793
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
Pair proxies with `generate_psobject`, which produces typed `Protocol` stubs
|
|
406
|
+
(including overloads) for IDE completion and static analysis:
|
|
412
407
|
|
|
413
|
-
|
|
414
|
-
|
|
408
|
+
```python
|
|
409
|
+
sh.generate_psobject("System.Text.StringBuilder()", Path("StringBuilder.py"))
|
|
415
410
|
```
|
|
416
411
|
|
|
417
|
-
|
|
412
|
+
```python
|
|
413
|
+
from StringBuilder import StringBuilder
|
|
418
414
|
|
|
419
|
-
|
|
420
|
-
|
|
415
|
+
sb = sh.make_proxy(StringBuilder) # created and typed in one call
|
|
416
|
+
sb.Append("Hello")
|
|
417
|
+
```
|
|
421
418
|
|
|
422
|
-
|
|
419
|
+
See the `make_proxy` and `generate_psobject` pages in the wiki.
|
|
423
420
|
|
|
424
|
-
##
|
|
421
|
+
## Core API overview
|
|
425
422
|
|
|
426
423
|
| Method | Description |
|
|
427
424
|
| ------------------------------ | ------------------------------- |
|
|
428
425
|
| `Shell.run(...)` | Execute a command synchronously |
|
|
429
426
|
| `Shell.run_async(...)` | Schedule async execution |
|
|
430
427
|
| `Shell.script(...)` | Run `.ps1` files |
|
|
431
|
-
| `Shell.save_session()` | Persist session snapshot
|
|
432
|
-
| `Shell.make_proxy(...)` | Create live PS object proxy
|
|
428
|
+
| `Shell.save_session()` | Persist a session snapshot |
|
|
429
|
+
| `Shell.make_proxy(...)` | Create a live PS object proxy |
|
|
433
430
|
| `Shell.generate_psobject(...)` | Generate Python `Protocol`s |
|
|
431
|
+
| `Shell.zero_copy_bridge()` | Shared per-shell bridge |
|
|
434
432
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
## ⚙️ Configuration example
|
|
433
|
+
## Configuration example
|
|
438
434
|
|
|
439
435
|
```python
|
|
440
436
|
Shell(
|
|
@@ -450,23 +446,36 @@ Shell(
|
|
|
450
446
|
)
|
|
451
447
|
```
|
|
452
448
|
|
|
453
|
-
|
|
449
|
+
## Performance
|
|
454
450
|
|
|
455
|
-
|
|
451
|
+
Measured with the bundled benchmarks (`bench/vs_bench.py`,
|
|
452
|
+
`bench/zcb_bench.py`) on Windows 11, Python 3.14, PowerShell 7:
|
|
456
453
|
|
|
457
|
-
|
|
454
|
+
**Command execution**
|
|
458
455
|
|
|
459
|
-
* ~
|
|
460
|
-
* ~3.
|
|
461
|
-
* ~2 ms
|
|
462
|
-
* ~
|
|
456
|
+
* ~0.45 s shell startup
|
|
457
|
+
* ~3.5–4.0 ms per sequential command (~280 cmd/s)
|
|
458
|
+
* ~3.2 ms per command in batches (~310 cmd/s)
|
|
459
|
+
* ~2.3 ms async latency
|
|
460
|
+
* ~620 cmd/s aggregate across 4 parallel shells
|
|
461
|
+
* ~0.35 s session save
|
|
463
462
|
|
|
464
|
-
|
|
463
|
+
**Zero-copy bridge** (best of 3 runs per size)
|
|
464
|
+
|
|
465
|
+
| Transfer | 1 MB | 8 MB | 32 MB |
|
|
466
|
+
| ----------------------------- | -------- | -------- | -------- |
|
|
467
|
+
| PowerShell → Python (bytes) | 145 MB/s | 385 MB/s | 413 MB/s |
|
|
468
|
+
| PowerShell → Python (memoryview) | 145 MB/s | 454 MB/s | 563 MB/s |
|
|
469
|
+
| Python → PowerShell (send) | 178 MB/s | 369 MB/s | 293 MB/s |
|
|
465
470
|
|
|
466
|
-
|
|
471
|
+
A 4 KB send+receive round trip takes ~8 ms (p50). For reference, moving the
|
|
472
|
+
same 1 MB payload through stdout as base64 runs at ~14 MB/s, so the bridge
|
|
473
|
+
is roughly 10–40× faster for bulk data.
|
|
474
|
+
|
|
475
|
+
Full methodology and charts live in the wiki.
|
|
467
476
|
|
|
468
|
-
##
|
|
477
|
+
## Learn more
|
|
469
478
|
|
|
470
|
-
*
|
|
471
|
-
*
|
|
472
|
-
*
|
|
479
|
+
* [Documentation wiki](https://github.com/Chamoswor/virtualshell/wiki)
|
|
480
|
+
* [Issues](https://github.com/Chamoswor/virtualshell/issues)
|
|
481
|
+
* [Discussions](https://github.com/Chamoswor/virtualshell/discussions)
|