virtualshell 0.1.2__cp310-cp310-win_amd64.whl → 1.0.1__cp310-cp310-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 +1 -1
- virtualshell/_core.cp310-win_amd64.pyd +0 -0
- virtualshell/_version.py +1 -1
- virtualshell/shell.py +13 -13
- {virtualshell-0.1.2.dist-info → virtualshell-1.0.1.dist-info}/METADATA +107 -180
- virtualshell-1.0.1.dist-info/RECORD +9 -0
- virtualshell-0.1.2.dist-info/RECORD +0 -9
- {virtualshell-0.1.2.dist-info → virtualshell-1.0.1.dist-info}/WHEEL +0 -0
- {virtualshell-0.1.2.dist-info → virtualshell-1.0.1.dist-info}/licenses/LICENSE +0 -0
virtualshell/__init__.py
CHANGED
Binary file
|
virtualshell/_version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
version = "0.1
|
1
|
+
version = "1.0.1"
|
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, "out", ""),
|
172
|
+
err=getattr(r, "err", ""),
|
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.1
|
3
|
+
Version: 1.0.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
|
@@ -219,40 +219,45 @@ Description-Content-Type: text/markdown
|
|
219
219
|
|
220
220
|
# virtualshell
|
221
221
|
|
222
|
-
High-performance Python façade over a **C++ PowerShell runner**.
|
223
|
-
|
222
|
+
High-performance Python façade over a **C++ PowerShell runner**.
|
223
|
+
A single long-lived PowerShell process is managed in C++, handling pipes, threads, timeouts and output demux; Python exposes a small, predictable API.
|
224
224
|
|
225
225
|
---
|
226
226
|
|
227
227
|
## Features
|
228
228
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
* **Context manager** (`with Shell(...)`) for lifecycle safety
|
229
|
+
- **Persistent session** to `pwsh`/`powershell` (reuse modules, `$env:*`, functions, cwd)
|
230
|
+
- **Sync & async** execution (Futures + optional callbacks)
|
231
|
+
- **Script execution** (positional / named args, optional dot-sourcing)
|
232
|
+
- **Batch** with per-command timeout & early-stop
|
233
|
+
- **Clear failures** (typed exceptions), **context manager** lifecycle
|
235
234
|
|
236
235
|
---
|
237
236
|
|
238
237
|
## Install
|
239
238
|
|
240
|
-
Preview packages are published to TestPyPI:
|
241
|
-
|
242
239
|
```bash
|
243
|
-
pip install
|
244
|
-
|
240
|
+
pip install virtualshell
|
241
|
+
````
|
242
|
+
|
243
|
+
## Platform & Python Support
|
245
244
|
|
246
|
-
|
245
|
+
Prebuilt wheels are provided via PyPI for common platforms and Python versions.
|
246
|
+
This means you can usually `pip install virtualshell` without needing a compiler.
|
247
247
|
|
248
|
+
**Supported Python versions:**
|
249
|
+
- 3.8, 3.9, 3.10, 3.11, 3.12, 3.13
|
248
250
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
> * Python 3.8–3.13 (matching the wheel you install)
|
251
|
+
**Supported platforms:**
|
252
|
+
- **Windows** (x86_64, MSVC build)
|
253
|
+
- **Linux** (x86_64, aarch64, manylinux2014/2.28)
|
254
|
+
- **macOS** (universal2: x86_64 + arm64)
|
254
255
|
|
255
|
-
|
256
|
+
If your platform is not listed above, pip will fall back to building from source.
|
257
|
+
See [Building from source](#building-from-source-advanced) for details.
|
258
|
+
|
259
|
+
|
260
|
+
> Requires PowerShell on `PATH` (`pwsh` preferred, `powershell` also supported).
|
256
261
|
|
257
262
|
---
|
258
263
|
|
@@ -265,88 +270,75 @@ import virtualshell
|
|
265
270
|
sh = virtualshell.Shell(timeout_seconds=5).start()
|
266
271
|
|
267
272
|
# 1) One-liners (sync)
|
268
|
-
res = sh.
|
269
|
-
print(res.
|
270
|
-
|
273
|
+
res = sh.run("Write-Output 'hello'")
|
274
|
+
print(res.out.strip()) # -> hello
|
271
275
|
|
272
|
-
#
|
273
|
-
fut = sh.
|
274
|
-
print(fut.result().
|
276
|
+
# 2) Async single command
|
277
|
+
fut = sh.run_async("Write-Output 'async!'")
|
278
|
+
print(fut.result().out.strip())
|
275
279
|
|
276
|
-
#
|
277
|
-
r = sh.
|
278
|
-
print(r.
|
280
|
+
# 3) Scripts with positional args
|
281
|
+
r = sh.run_script(r"C:\temp\demo.ps1", args=["alpha", "42"])
|
282
|
+
print(r.out)
|
279
283
|
|
280
|
-
#
|
281
|
-
r = sh.
|
282
|
-
print(r.
|
284
|
+
# 4) Scripts with named args
|
285
|
+
r = sh.run_script_kv(r"C:\temp\demo.ps1", named_args={"Name":"Alice","Count":"3"})
|
286
|
+
print(r.out)
|
283
287
|
|
284
|
-
#
|
288
|
+
# 5) Context manager (auto-stop on exit)
|
285
289
|
with virtualshell.Shell(timeout_seconds=3) as s:
|
286
|
-
print(s.
|
290
|
+
print(s.run("Write-Output 'inside with'").out.strip())
|
287
291
|
|
288
292
|
sh.stop()
|
289
293
|
```
|
290
294
|
|
295
|
+
Another example (stateful session):
|
296
|
+
|
291
297
|
```python
|
292
298
|
from virtualshell import Shell
|
293
299
|
with Shell(timeout_seconds=3) as sh:
|
294
|
-
sh.
|
295
|
-
nums = [sh.
|
296
|
-
print(nums) #
|
297
|
-
|
300
|
+
sh.run("function Inc { $global:i++; $global:i }")
|
301
|
+
nums = [sh.run("Inc").out.strip() for _ in range(5)]
|
302
|
+
print(nums) # ['1','2','3','4','5']
|
298
303
|
```
|
299
304
|
|
300
305
|
---
|
301
306
|
|
302
|
-
##
|
307
|
+
## API (overview)
|
303
308
|
|
304
309
|
```python
|
305
310
|
import virtualshell
|
306
|
-
from virtualshell import ExecutionResult #
|
311
|
+
from virtualshell import ExecutionResult # dataclass view
|
307
312
|
|
308
313
|
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"})
|
314
|
+
powershell_path=None, # optional explicit path
|
315
|
+
working_directory=None, # resolved to absolute path
|
316
|
+
timeout_seconds=5.0, # default per-command timeout
|
317
|
+
environment={"FOO": "BAR"}, # extra child env vars
|
318
|
+
initial_commands=["$ErrorActionPreference='Stop'"], # post-start setup
|
319
|
+
).start()
|
324
320
|
|
325
|
-
#
|
326
|
-
res = sh.
|
321
|
+
# Sync
|
322
|
+
res: ExecutionResult = sh.run("Get-Location | Select-Object -Expand Path")
|
327
323
|
|
328
|
-
#
|
329
|
-
|
330
|
-
|
324
|
+
# Scripts
|
325
|
+
res = sh.run_script(r"/path/to/job.ps1", args=["--fast","1"])
|
326
|
+
res = sh.run_script_kv(r"/path/to/job.ps1", named_args={"Mode":"Fast","Count":"1"})
|
327
|
+
res = sh.run_script(r"/path/init.ps1", dot_source=True)
|
331
328
|
|
332
|
-
|
333
|
-
|
329
|
+
# Async
|
330
|
+
f = sh.run_async("Write-Output 'ping'")
|
331
|
+
f2 = sh.run_async_batch(["$PSVersionTable", "Get-Random"])
|
334
332
|
|
335
|
-
|
336
|
-
|
337
|
-
# Async batch
|
338
|
-
f2 = sh.execute_async_batch(["$PSVersionTable", "Get-Random"])
|
339
|
-
print([r.success for r in f2.result()])
|
340
|
-
|
341
|
-
# --- Convenience ---
|
342
|
-
res = sh.pwsh("literal 'quoted' string") # safely single-quote literal data
|
333
|
+
# Convenience
|
334
|
+
res = sh.pwsh("literal 'quoted' string") # safe single-quoted literal
|
343
335
|
|
344
336
|
sh.stop()
|
345
337
|
```
|
346
338
|
|
347
|
-
### Return
|
339
|
+
### Return type
|
348
340
|
|
349
|
-
By default
|
341
|
+
By default you get a Python dataclass:
|
350
342
|
|
351
343
|
```python
|
352
344
|
@dataclass(frozen=True)
|
@@ -358,44 +350,39 @@ class ExecutionResult:
|
|
358
350
|
execution_time: float
|
359
351
|
```
|
360
352
|
|
361
|
-
Pass `as_dataclass=False` to receive the
|
353
|
+
Pass `as_dataclass=False` to receive the raw C++ result object.
|
362
354
|
|
363
355
|
### Timeouts
|
364
356
|
|
365
|
-
*
|
366
|
-
* On timeout
|
367
|
-
* Async futures resolve with the timeout result; late output is
|
357
|
+
* Every method accepts a `timeout` (or `per_command_timeout`) in seconds.
|
358
|
+
* On timeout: `success=False`, `exit_code=-1`, `error` contains `"timeout"`.
|
359
|
+
* Async futures resolve with the timeout result; late output is dropped in C++.
|
368
360
|
|
369
361
|
---
|
370
362
|
|
371
|
-
## Design
|
363
|
+
## Design notes
|
372
364
|
|
373
|
-
* **Thin wrapper:**
|
374
|
-
* **No surprises:**
|
375
|
-
* **Clear failure modes:**
|
376
|
-
* **Thread-friendly:**
|
377
|
-
* **Boundary hygiene:**
|
365
|
+
* **Thin wrapper:** heavy I/O in C++; Python does orchestration only.
|
366
|
+
* **No surprises:** stable API, documented side-effects.
|
367
|
+
* **Clear failure modes:** `raise_on_error` and typed exceptions.
|
368
|
+
* **Thread-friendly:** async returns Futures/callbacks; no Python GIL-level locking.
|
369
|
+
* **Boundary hygiene:** explicit path/arg conversions, minimal marshalling.
|
378
370
|
|
379
|
-
### Security
|
371
|
+
### Security
|
380
372
|
|
381
|
-
* The wrapper **does not sanitize** raw commands. Only `pwsh()`
|
382
|
-
*
|
383
|
-
*
|
373
|
+
* The wrapper **does not sanitize** raw commands. Only `pwsh()` applies literal single-quoting for data.
|
374
|
+
* Don’t pass untrusted strings to `run*` without proper quoting/sanitization.
|
375
|
+
* Avoid logging secrets; env injection happens via `Shell(..., environment=...)`.
|
384
376
|
|
385
|
-
### Performance
|
377
|
+
### Performance
|
386
378
|
|
387
|
-
* Sync/async routes call into C++ directly; Python overhead is
|
388
|
-
* Prefer **batch
|
379
|
+
* Sync/async routes call into C++ directly; Python overhead is object creation + callback dispatch.
|
380
|
+
* Prefer **batch/async** for many small commands to amortize round-trips.
|
389
381
|
|
390
382
|
### Lifetime
|
391
383
|
|
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.
|
384
|
+
* `Shell.start()` ensures a running backend; `Shell.stop()` tears it down.
|
385
|
+
* `with Shell(...)` guarantees stop-on-exit, even on exceptions.
|
399
386
|
|
400
387
|
---
|
401
388
|
|
@@ -403,29 +390,34 @@ Pass `as_dataclass=False` to receive the **raw C++ result object** for zero-copy
|
|
403
390
|
|
404
391
|
```python
|
405
392
|
from virtualshell.errors import (
|
406
|
-
|
393
|
+
VirtualShellError,
|
407
394
|
PowerShellNotFoundError,
|
408
395
|
ExecutionTimeoutError,
|
409
396
|
ExecutionError,
|
410
397
|
)
|
411
398
|
|
412
399
|
try:
|
413
|
-
res = sh.
|
400
|
+
res = sh.run("throw 'boom'", raise_on_error=True)
|
414
401
|
except ExecutionTimeoutError:
|
415
402
|
...
|
416
403
|
except ExecutionError as e:
|
417
|
-
print("
|
404
|
+
print("PowerShell failed:", e)
|
418
405
|
```
|
419
406
|
|
420
|
-
* `ExecutionTimeoutError` is raised
|
421
|
-
* Otherwise APIs return
|
407
|
+
* `ExecutionTimeoutError` is raised on timeouts **if** `raise_on_error=True`.
|
408
|
+
* Otherwise, APIs return `ExecutionResult(success=False)`.
|
422
409
|
|
423
410
|
---
|
424
411
|
|
425
412
|
## Configuration tips
|
426
413
|
|
427
|
-
|
428
|
-
|
414
|
+
If PowerShell isn’t on `PATH`, pass `powershell_path`:
|
415
|
+
|
416
|
+
```python
|
417
|
+
Shell(powershell_path=r"C:\Program Files\PowerShell\7\pwsh.exe")
|
418
|
+
```
|
419
|
+
|
420
|
+
Session setup example:
|
429
421
|
|
430
422
|
```python
|
431
423
|
Shell(initial_commands=[
|
@@ -436,107 +428,42 @@ Shell(initial_commands=[
|
|
436
428
|
|
437
429
|
---
|
438
430
|
|
439
|
-
|
440
|
-
|
441
|
-
You typically don’t need this when using wheels, but if you want to build locally:
|
442
|
-
|
443
|
-
### Prerequisites
|
444
|
-
|
445
|
-
* **Python** ≥ 3.8 with dev headers
|
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)
|
431
|
+
# Building from source (advanced)
|
432
|
+
Source builds require a C++ toolchain and CMake.
|
451
433
|
|
452
|
-
|
453
|
-
|
454
|
-
### One-shot local build (recommended)
|
434
|
+
**Prereqs:** Python ≥3.8, C++17, CMake ≥3.20, `scikit-build-core`, `pybind11`.
|
455
435
|
|
456
436
|
```bash
|
457
437
|
# in repo root
|
458
438
|
python -m pip install -U pip build
|
459
|
-
python -m build
|
439
|
+
python -m build # -> dist/*.whl, dist/*.tar.gz
|
460
440
|
python -m pip install dist/virtualshell-*.whl
|
461
441
|
```
|
462
442
|
|
463
|
-
|
443
|
+
Editable install:
|
464
444
|
|
465
445
|
```bash
|
466
|
-
python -m pip install -
|
467
|
-
python -m pip install -e . # uses scikit-build-core to build the C++ extension
|
446
|
+
python -m pip install -e .
|
468
447
|
```
|
469
448
|
|
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")`.
|
449
|
+
* Linux wheels target **manylinux_2_28** (x86_64/aarch64).
|
450
|
+
* macOS builds target **universal2** (x86_64 + arm64).
|
518
451
|
|
519
452
|
---
|
520
453
|
|
521
454
|
## Roadmap
|
522
455
|
|
523
456
|
* ✅ Windows x64 wheels (3.8–3.13)
|
524
|
-
* ✅ Linux x64 wheels (
|
457
|
+
* ✅ Linux x64/aarch64 wheels (manylinux_2_28)
|
458
|
+
* ✅ macOS x86_64/arm64 wheels
|
525
459
|
* ⏳ Streaming APIs and richer progress events
|
526
|
-
* ✅ Packaging polish (`pyproject`, build matrices, GitHub Actions)
|
527
460
|
|
528
461
|
---
|
529
462
|
|
530
463
|
## License
|
531
464
|
|
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.
|
465
|
+
Apache 2.0 — see [LICENSE](LICENSE).
|
539
466
|
|
540
467
|
---
|
541
468
|
|
542
|
-
*
|
469
|
+
*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=tmoVoFldry6oDZzejC_9ogkNcNkMe7X-DGEM0GKupEA,912
|
2
|
+
virtualshell/_core.cp310-win_amd64.pyd,sha256=tDSI-btEz-_V0SK63_Xz1xu171psBPnJsgKYbyxagUk,398336
|
3
|
+
virtualshell/_version.py,sha256=VAHPzEVbVY57udXNeljbTM8BnJ-ZHOJ6hSmLAd4CYgA,17
|
4
|
+
virtualshell/errors.py,sha256=fDblFND_Lz37HV5l6eKCkWXvrPXnI9_FfZs0bpEYFIU,196
|
5
|
+
virtualshell/shell.py,sha256=yR_i4S7DxdV-nmFop-fOnzXUAsUE52dTTkgP_uYPp2A,20910
|
6
|
+
virtualshell-1.0.1.dist-info/METADATA,sha256=zPJqTmAs3bCD9vD3RWKe458wfPAB1XMOLuoVZnIgAo0,20452
|
7
|
+
virtualshell-1.0.1.dist-info/WHEEL,sha256=hrGeChGtn46HBGmzasO9QQDSLelRN-tUarBSv4gFcsI,106
|
8
|
+
virtualshell-1.0.1.dist-info/licenses/LICENSE,sha256=34HMvl-jxuw-TVFRK7do9XGJkawVmiiwmPGFfZACBpI,11548
|
9
|
+
virtualshell-1.0.1.dist-info/RECORD,,
|
@@ -1,9 +0,0 @@
|
|
1
|
-
virtualshell/__init__.py,sha256=8PE1B8yiMyZg2gwG18EvXt2vDEflvBeAdh7mNn58-GE,912
|
2
|
-
virtualshell/_core.cp310-win_amd64.pyd,sha256=yKNvheTGFhg_gy9Lstl-ejZJiPQdEBKPgFyMFTi-NC4,398336
|
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=hrGeChGtn46HBGmzasO9QQDSLelRN-tUarBSv4gFcsI,106
|
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
|