virtualshell 0.1.2__cp38-cp38-win_amd64.whl → 1.0.0__cp38-cp38-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/_core.cp38-win_amd64.pyd +0 -0
- virtualshell/shell.py +13 -13
- {virtualshell-0.1.2.dist-info → virtualshell-1.0.0.dist-info}/METADATA +99 -180
- virtualshell-1.0.0.dist-info/RECORD +9 -0
- virtualshell-0.1.2.dist-info/RECORD +0 -9
- {virtualshell-0.1.2.dist-info → virtualshell-1.0.0.dist-info}/WHEEL +0 -0
- {virtualshell-0.1.2.dist-info → virtualshell-1.0.0.dist-info}/licenses/LICENSE +0 -0
Binary file
|
virtualshell/shell.py
CHANGED
@@ -158,8 +158,8 @@ class ExecutionResult:
|
|
158
158
|
Use this class when you need a stable Pythonic type. If you require the raw C++
|
159
159
|
object (e.g., for zero-copy interop), pass `as_dataclass=False` to public APIs.
|
160
160
|
"""
|
161
|
-
|
162
|
-
|
161
|
+
out: str
|
162
|
+
err: str
|
163
163
|
exit_code: int
|
164
164
|
success: bool
|
165
165
|
execution_time: float
|
@@ -168,8 +168,8 @@ class ExecutionResult:
|
|
168
168
|
def from_cpp(cls, r: _CPP_ExecResult) -> "ExecutionResult":
|
169
169
|
# Attribute access is defensive to tolerate ABI field name differences.
|
170
170
|
return cls(
|
171
|
-
|
172
|
-
|
171
|
+
out=getattr(r, "output", ""),
|
172
|
+
err=getattr(r, "error", ""),
|
173
173
|
exit_code=int(getattr(r, "exit_code", getattr(r, "exitCode", -1))),
|
174
174
|
success=bool(getattr(r, "success", False)),
|
175
175
|
execution_time=float(getattr(r, "execution_time", getattr(r, "executionTime", 0.0))),
|
@@ -265,7 +265,7 @@ class Shell:
|
|
265
265
|
return bool(self._core.is_alive())
|
266
266
|
|
267
267
|
# -------- sync --------
|
268
|
-
def
|
268
|
+
def run(
|
269
269
|
self,
|
270
270
|
command: str,
|
271
271
|
timeout: Optional[float] = None,
|
@@ -291,7 +291,7 @@ class Shell:
|
|
291
291
|
_raise_on_failure(res, raise_on_error=raise_on_error, label="Command", timeout_used=to)
|
292
292
|
return ExecutionResult.from_cpp(res) if as_dataclass else res
|
293
293
|
|
294
|
-
def
|
294
|
+
def run_script(
|
295
295
|
self,
|
296
296
|
script_path: Union[str, Path],
|
297
297
|
args: Optional[Iterable[str]] = None,
|
@@ -320,7 +320,7 @@ class Shell:
|
|
320
320
|
_raise_on_failure(res, raise_on_error=raise_on_error, label="Script", timeout_used=to)
|
321
321
|
return ExecutionResult.from_cpp(res) if as_dataclass else res
|
322
322
|
|
323
|
-
def
|
323
|
+
def run_script_kv(
|
324
324
|
self,
|
325
325
|
script_path: Union[str, Path],
|
326
326
|
named_args: Optional[Dict[str, str]] = None,
|
@@ -346,7 +346,7 @@ class Shell:
|
|
346
346
|
_raise_on_failure(res, raise_on_error=raise_on_error, label="ScriptKV", timeout_used=to)
|
347
347
|
return ExecutionResult.from_cpp(res) if as_dataclass else res
|
348
348
|
|
349
|
-
def
|
349
|
+
def run_batch(
|
350
350
|
self,
|
351
351
|
commands: Iterable[str],
|
352
352
|
*,
|
@@ -369,7 +369,7 @@ class Shell:
|
|
369
369
|
return [ExecutionResult.from_cpp(r) for r in vec]
|
370
370
|
return vec
|
371
371
|
|
372
|
-
def
|
372
|
+
def run_async(self, command: str, callback: Optional[Callable[[ExecutionResult], None]] = None, *, as_dataclass: bool = True):
|
373
373
|
"""Asynchronously execute a single command.
|
374
374
|
|
375
375
|
- If `callback` is provided, it is invoked on completion with the result type
|
@@ -390,7 +390,7 @@ class Shell:
|
|
390
390
|
c_fut = self._core.execute_async(command=command, callback=_cb if callback else None)
|
391
391
|
return _map_future(c_fut, lambda r: ExecutionResult.from_cpp(r)) if as_dataclass else c_fut
|
392
392
|
|
393
|
-
def
|
393
|
+
def run_async_batch(
|
394
394
|
self,
|
395
395
|
commands: Iterable[str],
|
396
396
|
progress: Optional[Callable[[ _CPP_BatchProg ], None]] = None,
|
@@ -416,7 +416,7 @@ class Shell:
|
|
416
416
|
return _map_future(fut, lambda vec: [ExecutionResult.from_cpp(r) for r in vec])
|
417
417
|
return fut
|
418
418
|
|
419
|
-
def
|
419
|
+
def run_async_script(
|
420
420
|
self,
|
421
421
|
script_path: Union[str, Path],
|
422
422
|
args: Optional[Iterable[str]] = None,
|
@@ -453,7 +453,7 @@ class Shell:
|
|
453
453
|
return _map_future(fut, lambda r: ExecutionResult.from_cpp(r))
|
454
454
|
return fut
|
455
455
|
|
456
|
-
def
|
456
|
+
def run_async_script_kv(
|
457
457
|
self,
|
458
458
|
script_path: Union[str, Path],
|
459
459
|
named_args: Optional[Dict[str, str]] = None,
|
@@ -501,7 +501,7 @@ class Shell:
|
|
501
501
|
`shell.pwsh("Hello 'World'")` -> runs `Write-Output 'Hello ''World'''` semantics;
|
502
502
|
here we only quote the literal; you still provide the full command.
|
503
503
|
"""
|
504
|
-
return self.
|
504
|
+
return self.run(quote_pwsh_literal(s), timeout=timeout, raise_on_error=raise_on_error)
|
505
505
|
|
506
506
|
def __enter__(self) -> "Shell":
|
507
507
|
"""Context manager entry: ensure backend is running."""
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: virtualshell
|
3
|
-
Version: 0.
|
3
|
+
Version: 1.0.0
|
4
4
|
Summary: High-performance PowerShell bridge (C++ pybind11 backend)
|
5
5
|
Keywords: powershell,automation,shell,cpp,pybind11
|
6
6
|
Author: Kim-Andre Myrvold
|
@@ -217,42 +217,38 @@ Project-URL: Issues, https://github.com/Chamoswor/virtualshell/issues
|
|
217
217
|
Requires-Python: >=3.8
|
218
218
|
Description-Content-Type: text/markdown
|
219
219
|
|
220
|
+
````markdown
|
220
221
|
# virtualshell
|
221
222
|
|
222
|
-
High-performance Python façade over a **C++ PowerShell runner**.
|
223
|
-
|
223
|
+
High-performance Python façade over a **C++ PowerShell runner**.
|
224
|
+
A single long-lived PowerShell process is managed in C++, handling pipes, threads, timeouts and output demux; Python exposes a small, predictable API.
|
224
225
|
|
225
226
|
---
|
226
227
|
|
227
228
|
## Features
|
228
229
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
* **Context manager** (`with Shell(...)`) for lifecycle safety
|
230
|
+
- **Persistent session** to `pwsh`/`powershell` (reuse modules, `$env:*`, functions, cwd)
|
231
|
+
- **Sync & async** execution (Futures + optional callbacks)
|
232
|
+
- **Script execution** (positional / named args, optional dot-sourcing)
|
233
|
+
- **Batch** with per-command timeout & early-stop
|
234
|
+
- **Clear failures** (typed exceptions), **context manager** lifecycle
|
235
235
|
|
236
236
|
---
|
237
237
|
|
238
238
|
## Install
|
239
239
|
|
240
|
-
Preview packages are published to TestPyPI:
|
241
|
-
|
242
240
|
```bash
|
243
|
-
pip install
|
244
|
-
|
245
|
-
|
246
|
-
### Available distributions (Windows/Linux, amd64/x86_64)
|
241
|
+
pip install virtualshell
|
242
|
+
````
|
247
243
|
|
244
|
+
### Supported platforms
|
248
245
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
> * Python 3.8–3.13 (matching the wheel you install)
|
246
|
+
* **Windows 10/11 x64**
|
247
|
+
* **Linux**: x86_64 and aarch64 (manylinux_2_28 / glibc ≥ 2.28)
|
248
|
+
* **macOS**: 12+ (x86_64 and arm64)
|
249
|
+
* **Python**: 3.8 – 3.13
|
254
250
|
|
255
|
-
|
251
|
+
> Requires PowerShell on `PATH` (`pwsh` preferred, `powershell` also supported).
|
256
252
|
|
257
253
|
---
|
258
254
|
|
@@ -265,88 +261,75 @@ import virtualshell
|
|
265
261
|
sh = virtualshell.Shell(timeout_seconds=5).start()
|
266
262
|
|
267
263
|
# 1) One-liners (sync)
|
268
|
-
res = sh.
|
269
|
-
print(res.
|
264
|
+
res = sh.run("Write-Output 'hello'")
|
265
|
+
print(res.out.strip()) # -> hello
|
270
266
|
|
267
|
+
# 2) Async single command
|
268
|
+
fut = sh.run_async("Write-Output 'async!'")
|
269
|
+
print(fut.result().out.strip())
|
271
270
|
|
272
|
-
# 3)
|
273
|
-
|
274
|
-
print(
|
271
|
+
# 3) Scripts with positional args
|
272
|
+
r = sh.run_script(r"C:\temp\demo.ps1", args=["alpha", "42"])
|
273
|
+
print(r.out)
|
275
274
|
|
276
|
-
# 4) Scripts with
|
277
|
-
r = sh.
|
278
|
-
print(r.
|
275
|
+
# 4) Scripts with named args
|
276
|
+
r = sh.run_script_kv(r"C:\temp\demo.ps1", named_args={"Name":"Alice","Count":"3"})
|
277
|
+
print(r.out)
|
279
278
|
|
280
|
-
# 5)
|
281
|
-
r = sh.execute_script_kv(r"C:\temp\demo.ps1", named_args={"Name":"Alice", "Count":"3"})
|
282
|
-
print(r.output)
|
283
|
-
|
284
|
-
# 6) Context manager (auto-stop on exit)
|
279
|
+
# 5) Context manager (auto-stop on exit)
|
285
280
|
with virtualshell.Shell(timeout_seconds=3) as s:
|
286
|
-
print(s.
|
281
|
+
print(s.run("Write-Output 'inside with'").out.strip())
|
287
282
|
|
288
283
|
sh.stop()
|
289
284
|
```
|
290
285
|
|
286
|
+
Another example (stateful session):
|
287
|
+
|
291
288
|
```python
|
292
289
|
from virtualshell import Shell
|
293
290
|
with Shell(timeout_seconds=3) as sh:
|
294
|
-
sh.
|
295
|
-
nums = [sh.
|
296
|
-
print(nums) #
|
297
|
-
|
291
|
+
sh.run("function Inc { $global:i++; $global:i }")
|
292
|
+
nums = [sh.run("Inc").out.strip() for _ in range(5)]
|
293
|
+
print(nums) # ['1','2','3','4','5']
|
298
294
|
```
|
299
295
|
|
300
296
|
---
|
301
297
|
|
302
|
-
##
|
298
|
+
## API (overview)
|
303
299
|
|
304
300
|
```python
|
305
301
|
import virtualshell
|
306
|
-
from virtualshell import ExecutionResult #
|
302
|
+
from virtualshell import ExecutionResult # dataclass view
|
307
303
|
|
308
304
|
sh = virtualshell.Shell(
|
309
|
-
powershell_path=None,
|
310
|
-
working_directory=None,
|
311
|
-
timeout_seconds=5.0,
|
312
|
-
environment={"FOO":"BAR"},
|
313
|
-
initial_commands=["$ErrorActionPreference='Stop'"] #
|
314
|
-
)
|
315
|
-
|
316
|
-
sh.start() # idempotent, safe if already running
|
317
|
-
|
318
|
-
# --- Sync ---
|
319
|
-
res: ExecutionResult = sh.execute("Get-Location | Select-Object -Expand Path")
|
320
|
-
print(res.success, res.exit_code, res.output)
|
321
|
-
|
322
|
-
res = sh.execute_script(r"C:\scripts\job.ps1", args=["--fast","1"])
|
323
|
-
res = sh.execute_script_kv(r"C:\scripts\job.ps1", named_args={"Mode":"Fast","Count":"1"})
|
324
|
-
|
325
|
-
# Dotsource script
|
326
|
-
res = sh.execute_script(r"C:\scripts\init.ps1", dot_source=True)
|
305
|
+
powershell_path=None, # optional explicit path
|
306
|
+
working_directory=None, # resolved to absolute path
|
307
|
+
timeout_seconds=5.0, # default per-command timeout
|
308
|
+
environment={"FOO": "BAR"}, # extra child env vars
|
309
|
+
initial_commands=["$ErrorActionPreference='Stop'"], # post-start setup
|
310
|
+
).start()
|
327
311
|
|
328
|
-
#
|
329
|
-
|
330
|
-
print(f.result().output.strip())
|
312
|
+
# Sync
|
313
|
+
res: ExecutionResult = sh.run("Get-Location | Select-Object -Expand Path")
|
331
314
|
|
332
|
-
|
333
|
-
|
315
|
+
# Scripts
|
316
|
+
res = sh.run_script(r"/path/to/job.ps1", args=["--fast","1"])
|
317
|
+
res = sh.run_script_kv(r"/path/to/job.ps1", named_args={"Mode":"Fast","Count":"1"})
|
318
|
+
res = sh.run_script(r"/path/init.ps1", dot_source=True)
|
334
319
|
|
335
|
-
|
320
|
+
# Async
|
321
|
+
f = sh.run_async("Write-Output 'ping'")
|
322
|
+
f2 = sh.run_async_batch(["$PSVersionTable", "Get-Random"])
|
336
323
|
|
337
|
-
#
|
338
|
-
|
339
|
-
print([r.success for r in f2.result()])
|
340
|
-
|
341
|
-
# --- Convenience ---
|
342
|
-
res = sh.pwsh("literal 'quoted' string") # safely single-quote literal data
|
324
|
+
# Convenience
|
325
|
+
res = sh.pwsh("literal 'quoted' string") # safe single-quoted literal
|
343
326
|
|
344
327
|
sh.stop()
|
345
328
|
```
|
346
329
|
|
347
|
-
### Return
|
330
|
+
### Return type
|
348
331
|
|
349
|
-
By default
|
332
|
+
By default you get a Python dataclass:
|
350
333
|
|
351
334
|
```python
|
352
335
|
@dataclass(frozen=True)
|
@@ -358,44 +341,39 @@ class ExecutionResult:
|
|
358
341
|
execution_time: float
|
359
342
|
```
|
360
343
|
|
361
|
-
Pass `as_dataclass=False` to receive the
|
344
|
+
Pass `as_dataclass=False` to receive the raw C++ result object.
|
362
345
|
|
363
346
|
### Timeouts
|
364
347
|
|
365
|
-
*
|
366
|
-
* On timeout
|
367
|
-
* Async futures resolve with the timeout result; late output is
|
348
|
+
* Every method accepts a `timeout` (or `per_command_timeout`) in seconds.
|
349
|
+
* On timeout: `success=False`, `exit_code=-1`, `error` contains `"timeout"`.
|
350
|
+
* Async futures resolve with the timeout result; late output is dropped in C++.
|
368
351
|
|
369
352
|
---
|
370
353
|
|
371
|
-
## Design
|
354
|
+
## Design notes
|
372
355
|
|
373
|
-
* **Thin wrapper:**
|
374
|
-
* **No surprises:**
|
375
|
-
* **Clear failure modes:**
|
376
|
-
* **Thread-friendly:**
|
377
|
-
* **Boundary hygiene:**
|
356
|
+
* **Thin wrapper:** heavy I/O in C++; Python does orchestration only.
|
357
|
+
* **No surprises:** stable API, documented side-effects.
|
358
|
+
* **Clear failure modes:** `raise_on_error` and typed exceptions.
|
359
|
+
* **Thread-friendly:** async returns Futures/callbacks; no Python GIL-level locking.
|
360
|
+
* **Boundary hygiene:** explicit path/arg conversions, minimal marshalling.
|
378
361
|
|
379
|
-
### Security
|
362
|
+
### Security
|
380
363
|
|
381
|
-
* The wrapper **does not sanitize** raw commands. Only `pwsh()`
|
382
|
-
*
|
383
|
-
*
|
364
|
+
* The wrapper **does not sanitize** raw commands. Only `pwsh()` applies literal single-quoting for data.
|
365
|
+
* Don’t pass untrusted strings to `run*` without proper quoting/sanitization.
|
366
|
+
* Avoid logging secrets; env injection happens via `Shell(..., environment=...)`.
|
384
367
|
|
385
|
-
### Performance
|
368
|
+
### Performance
|
386
369
|
|
387
|
-
* Sync/async routes call into C++ directly; Python overhead is
|
388
|
-
* Prefer **batch
|
370
|
+
* Sync/async routes call into C++ directly; Python overhead is object creation + callback dispatch.
|
371
|
+
* Prefer **batch/async** for many small commands to amortize round-trips.
|
389
372
|
|
390
373
|
### Lifetime
|
391
374
|
|
392
|
-
* `Shell.start()`
|
393
|
-
* `with Shell(...)
|
394
|
-
|
395
|
-
### Compatibility
|
396
|
-
|
397
|
-
* The C++ layer may expose both `snake_case` and `camelCase`.
|
398
|
-
* `ExecutionResult.from_cpp()` normalizes fields to keep ABI compatibility.
|
375
|
+
* `Shell.start()` ensures a running backend; `Shell.stop()` tears it down.
|
376
|
+
* `with Shell(...)` guarantees stop-on-exit, even on exceptions.
|
399
377
|
|
400
378
|
---
|
401
379
|
|
@@ -403,29 +381,34 @@ Pass `as_dataclass=False` to receive the **raw C++ result object** for zero-copy
|
|
403
381
|
|
404
382
|
```python
|
405
383
|
from virtualshell.errors import (
|
406
|
-
|
384
|
+
VirtualShellError,
|
407
385
|
PowerShellNotFoundError,
|
408
386
|
ExecutionTimeoutError,
|
409
387
|
ExecutionError,
|
410
388
|
)
|
411
389
|
|
412
390
|
try:
|
413
|
-
res = sh.
|
391
|
+
res = sh.run("throw 'boom'", raise_on_error=True)
|
414
392
|
except ExecutionTimeoutError:
|
415
393
|
...
|
416
394
|
except ExecutionError as e:
|
417
|
-
print("
|
395
|
+
print("PowerShell failed:", e)
|
418
396
|
```
|
419
397
|
|
420
|
-
* `ExecutionTimeoutError` is raised
|
421
|
-
* Otherwise APIs return
|
398
|
+
* `ExecutionTimeoutError` is raised on timeouts **if** `raise_on_error=True`.
|
399
|
+
* Otherwise, APIs return `ExecutionResult(success=False)`.
|
422
400
|
|
423
401
|
---
|
424
402
|
|
425
403
|
## Configuration tips
|
426
404
|
|
427
|
-
|
428
|
-
|
405
|
+
If PowerShell isn’t on `PATH`, pass `powershell_path`:
|
406
|
+
|
407
|
+
```python
|
408
|
+
Shell(powershell_path=r"C:\Program Files\PowerShell\7\pwsh.exe")
|
409
|
+
```
|
410
|
+
|
411
|
+
Session setup example:
|
429
412
|
|
430
413
|
```python
|
431
414
|
Shell(initial_commands=[
|
@@ -436,107 +419,43 @@ Shell(initial_commands=[
|
|
436
419
|
|
437
420
|
---
|
438
421
|
|
439
|
-
## Building from source (
|
440
|
-
|
441
|
-
You typically don’t need this when using wheels, but if you want to build locally:
|
442
|
-
|
443
|
-
### Prerequisites
|
422
|
+
## Building from source (optional)
|
444
423
|
|
445
|
-
|
446
|
-
* **C++17** compiler
|
447
|
-
* **CMake** ≥ 3.20
|
448
|
-
* **Build backend:** [`scikit-build-core`](https://github.com/scikit-build/scikit-build-core) + [`pybind11`](https://pybind11.readthedocs.io/)
|
449
|
-
* **Windows:** MSVC (VS 2019/2022)
|
450
|
-
* **Linux:** GCC/Clang (Linux wheels not verified yet)
|
424
|
+
You normally won’t need this when using wheels.
|
451
425
|
|
452
|
-
|
453
|
-
|
454
|
-
### One-shot local build (recommended)
|
426
|
+
**Prereqs:** Python ≥3.8, C++17, CMake ≥3.20, `scikit-build-core`, `pybind11`.
|
455
427
|
|
456
428
|
```bash
|
457
429
|
# in repo root
|
458
430
|
python -m pip install -U pip build
|
459
|
-
python -m build
|
431
|
+
python -m build # -> dist/*.whl, dist/*.tar.gz
|
460
432
|
python -m pip install dist/virtualshell-*.whl
|
461
433
|
```
|
462
434
|
|
463
|
-
|
435
|
+
Editable install:
|
464
436
|
|
465
437
|
```bash
|
466
|
-
python -m pip install -
|
467
|
-
python -m pip install -e . # uses scikit-build-core to build the C++ extension
|
438
|
+
python -m pip install -e .
|
468
439
|
```
|
469
440
|
|
470
|
-
|
471
|
-
|
472
|
-
**Windows (x64)**
|
473
|
-
|
474
|
-
* Visual Studio 2022 generator is used by default (see `[tool.scikit-build.cmake]` in `pyproject.toml`).
|
475
|
-
* If you have multiple VS versions, ensure the correct **x64** toolchain is active (Developer Command Prompt or `vcvars64.bat`).
|
476
|
-
|
477
|
-
**Linux (x86_64)**
|
478
|
-
|
479
|
-
* Source builds work with a recent GCC/Clang + CMake.
|
480
|
-
* Prebuilt manylinux wheels are **not** published yet; CI configuration exists, but the Linux runtime matrix is still being validated.
|
481
|
-
|
482
|
-
### Build configuration
|
483
|
-
|
484
|
-
Most options are declared in `pyproject.toml`:
|
485
|
-
|
486
|
-
* **Backend:** `scikit_build_core.build`
|
487
|
-
* **Build args:** CMake generator and `PYBIND11_FINDPYTHON=ON` are set (auto-discovers the active Python).
|
488
|
-
* **Wheel layout:** packaged under `src/virtualshell/`
|
489
|
-
* **Versioning:** `setuptools_scm` writes `src/virtualshell/_version.py` from Git tags.
|
490
|
-
|
491
|
-
You can override or pass extra CMake definitions at build time if needed:
|
492
|
-
|
493
|
-
```bash
|
494
|
-
# Example: switch generator or tweak parallelism
|
495
|
-
SCIKIT_BUILD_VERBOSE=1 \
|
496
|
-
CMAKE_BUILD_PARALLEL_LEVEL=8 \
|
497
|
-
python -m build
|
498
|
-
```
|
499
|
-
|
500
|
-
### Smoke test after build
|
501
|
-
|
502
|
-
```bash
|
503
|
-
python - << 'PY'
|
504
|
-
import virtualshell
|
505
|
-
s = virtualshell.Shell(timeout_seconds=2)
|
506
|
-
print("import_ok:", bool(s._core))
|
507
|
-
# Optional: only if PowerShell is available on PATH
|
508
|
-
# if s.start().is_running:
|
509
|
-
# print("exec_ok:", virtualshell.Shell().start().execute("Write-Output 'ok'").success)
|
510
|
-
PY
|
511
|
-
```
|
512
|
-
|
513
|
-
### Troubleshooting
|
514
|
-
|
515
|
-
* **Cannot find MSVC/CMake:** open a *Developer Command Prompt for VS 2022* or ensure `cmake` and the MSVC toolchain are on `PATH`.
|
516
|
-
* **ImportError: cannot import name `_core`:** the extension didn’t build or wasn’t placed under `virtualshell/_core.*`. Reinstall (`python -m pip install -e .` or `python -m build && pip install dist/*.whl`).
|
517
|
-
* **PowerShell not found at runtime:** pass an explicit path: `Shell(powershell_path=r"C:\Program Files\PowerShell\7\pwsh.exe")`.
|
441
|
+
* Linux wheels target **manylinux_2_28** (x86_64/aarch64).
|
442
|
+
* macOS builds target **x86_64** and **arm64** (may be universal2).
|
518
443
|
|
519
444
|
---
|
520
445
|
|
521
446
|
## Roadmap
|
522
447
|
|
523
448
|
* ✅ Windows x64 wheels (3.8–3.13)
|
524
|
-
* ✅ Linux x64 wheels (
|
449
|
+
* ✅ Linux x64/aarch64 wheels (manylinux_2_28)
|
450
|
+
* ✅ macOS x86_64/arm64 wheels
|
525
451
|
* ⏳ Streaming APIs and richer progress events
|
526
|
-
* ✅ Packaging polish (`pyproject`, build matrices, GitHub Actions)
|
527
452
|
|
528
453
|
---
|
529
454
|
|
530
455
|
## License
|
531
456
|
|
532
|
-
Apache 2.0
|
533
|
-
|
534
|
-
---
|
535
|
-
|
536
|
-
## Acknowledgments
|
537
|
-
|
538
|
-
* Built with `pybind11`, and a lot of care around cross-platform pipes & process control.
|
457
|
+
Apache 2.0 — see [LICENSE](LICENSE).
|
539
458
|
|
540
459
|
---
|
541
460
|
|
542
|
-
*
|
461
|
+
*Issues & feedback are welcome. Please include Python version, OS, your PowerShell path (`pwsh`/`powershell`), and a minimal repro.*
|
@@ -0,0 +1,9 @@
|
|
1
|
+
virtualshell/__init__.py,sha256=8PE1B8yiMyZg2gwG18EvXt2vDEflvBeAdh7mNn58-GE,912
|
2
|
+
virtualshell/_core.cp38-win_amd64.pyd,sha256=1NsRfNORXFcAM1kUv2r3bk4aNFgJWMU6Kw4ZChSsUWg,397824
|
3
|
+
virtualshell/_version.py,sha256=ZgAXEMjAMZx3cZroB6PgojYwdhTZjPbU5RqZEfdYQv0,17
|
4
|
+
virtualshell/errors.py,sha256=fDblFND_Lz37HV5l6eKCkWXvrPXnI9_FfZs0bpEYFIU,196
|
5
|
+
virtualshell/shell.py,sha256=iHEFnbY3ggR2G-VpxAHrP3RVx3nYy1S2VxxLUTLRHa4,20915
|
6
|
+
virtualshell-1.0.0.dist-info/METADATA,sha256=C0_uXHh7-Lxslvmqo8JBOW1M5gK8D1YieCEVQgWf21c,20087
|
7
|
+
virtualshell-1.0.0.dist-info/WHEEL,sha256=yXMtVL9U8RkqJEJfb-z5X2s1_G1r2eGG-REYk3wgjZ0,104
|
8
|
+
virtualshell-1.0.0.dist-info/licenses/LICENSE,sha256=34HMvl-jxuw-TVFRK7do9XGJkawVmiiwmPGFfZACBpI,11548
|
9
|
+
virtualshell-1.0.0.dist-info/RECORD,,
|
@@ -1,9 +0,0 @@
|
|
1
|
-
virtualshell/__init__.py,sha256=8PE1B8yiMyZg2gwG18EvXt2vDEflvBeAdh7mNn58-GE,912
|
2
|
-
virtualshell/_core.cp38-win_amd64.pyd,sha256=4dGWTK_k3CQuv9Uc16sHTGt-Z9LTzz8BX-cLL3hHiJQ,397824
|
3
|
-
virtualshell/_version.py,sha256=ZgAXEMjAMZx3cZroB6PgojYwdhTZjPbU5RqZEfdYQv0,17
|
4
|
-
virtualshell/errors.py,sha256=fDblFND_Lz37HV5l6eKCkWXvrPXnI9_FfZs0bpEYFIU,196
|
5
|
-
virtualshell/shell.py,sha256=gMknFPVMWpQzsEbc-JX9VD0xtPHkxz5SS5TU521lP0Q,20961
|
6
|
-
virtualshell-0.1.2.dist-info/METADATA,sha256=qdLeHdMI-gCwyIrAwNeN5i1S1n7A0Z6ZB6b_56Ri5mM,23684
|
7
|
-
virtualshell-0.1.2.dist-info/WHEEL,sha256=yXMtVL9U8RkqJEJfb-z5X2s1_G1r2eGG-REYk3wgjZ0,104
|
8
|
-
virtualshell-0.1.2.dist-info/licenses/LICENSE,sha256=34HMvl-jxuw-TVFRK7do9XGJkawVmiiwmPGFfZACBpI,11548
|
9
|
-
virtualshell-0.1.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|