boxlite 0.5.7__cp312-cp312-macosx_14_0_arm64.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 boxlite might be problematic. Click here for more details.

@@ -0,0 +1,845 @@
1
+ Metadata-Version: 2.4
2
+ Name: boxlite
3
+ Version: 0.5.7
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: Apache Software License
7
+ Classifier: Programming Language :: Python :: 3.10
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Rust
12
+ Classifier: Operating System :: MacOS
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
15
+ Classifier: Topic :: Security
16
+ Classifier: Topic :: System :: Emulators
17
+ Requires-Dist: pytest>=7.0 ; extra == 'dev'
18
+ Requires-Dist: pytest-asyncio>=0.21 ; extra == 'dev'
19
+ Requires-Dist: greenlet>=3.0.0 ; extra == 'sync'
20
+ Provides-Extra: dev
21
+ Provides-Extra: sync
22
+ Summary: Python bindings for Boxlite runtime
23
+ Keywords: sandbox,virtual machine,vm,ai agents,code execution,isolation,container,security,kvm,hypervisor
24
+ Author: Dorian Zheng
25
+ License-Expression: Apache-2.0
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
28
+ Project-URL: Documentation, https://github.com/boxlite-ai/boxlite/tree/main/docs
29
+ Project-URL: Homepage, https://github.com/boxlite-ai/boxlite
30
+ Project-URL: Issues, https://github.com/boxlite-ai/boxlite/issues
31
+ Project-URL: Repository, https://github.com/boxlite-ai/boxlite
32
+
33
+ # BoxLite Python SDK
34
+
35
+ Python bindings for BoxLite - an embeddable virtual machine runtime for secure, isolated code execution.
36
+
37
+ ## Overview
38
+
39
+ The BoxLite Python SDK provides a Pythonic API for creating and managing isolated execution environments. Built with PyO3, it wraps the Rust BoxLite runtime with async-first Python bindings.
40
+
41
+ **Version:** 0.4.4
42
+ **Python:** 3.10+
43
+ **Platforms:** macOS (Apple Silicon), Linux (x86_64, ARM64)
44
+
45
+ ### Key Features
46
+
47
+ - **Async-first API** - All I/O operations use async/await
48
+ - **Context managers** - Automatic cleanup with `async with`
49
+ - **Streaming I/O** - Real-time stdout/stderr as execution happens
50
+ - **Multiple box types** - SimpleBox, CodeBox, BrowserBox, ComputerBox, InteractiveBox
51
+ - **Resource control** - Configure CPUs, memory, volumes, ports
52
+ - **OCI compatible** - Use any Docker/OCI image
53
+
54
+ ## Installation
55
+
56
+ ```bash
57
+ pip install boxlite
58
+ ```
59
+
60
+ Requires Python 3.10 or later.
61
+
62
+ ### Verify Installation
63
+
64
+ ```python
65
+ import boxlite
66
+ print(boxlite.__version__) # Should print: 0.4.4
67
+ ```
68
+
69
+ ### System Requirements
70
+
71
+ | Platform | Architecture | Requirements |
72
+ |----------|---------------|-------------------------------------|
73
+ | macOS | Apple Silicon | macOS 12+ |
74
+ | Linux | x86_64, ARM64 | KVM enabled (`/dev/kvm` accessible) |
75
+
76
+ On Linux, verify KVM is available:
77
+ ```bash
78
+ grep -E 'vmx|svm' /proc/cpuinfo # Should show CPU virtualization support
79
+ ls -l /dev/kvm # Should exist and be accessible
80
+ ```
81
+
82
+ ## Quick Start
83
+
84
+ ### Basic Execution
85
+
86
+ ```python
87
+ import asyncio
88
+ import boxlite
89
+
90
+ async def main():
91
+ # Create a box and run a command
92
+ async with boxlite.SimpleBox(image="python:slim") as box:
93
+ result = await box.exec("python", "-c", "print('Hello from BoxLite!')")
94
+ print(result.stdout)
95
+ # Output: Hello from BoxLite!
96
+
97
+ asyncio.run(main())
98
+ ```
99
+
100
+ ### Code Execution (AI Agents)
101
+
102
+ ```python
103
+ import asyncio
104
+ import boxlite
105
+
106
+ async def main():
107
+ # Execute untrusted Python code safely
108
+ code = """
109
+ import requests
110
+ response = requests.get('https://api.github.com/zen')
111
+ print(response.text)
112
+ """
113
+
114
+ async with boxlite.CodeBox() as codebox:
115
+ # CodeBox automatically installs packages
116
+ result = await codebox.run(code)
117
+ print(result)
118
+
119
+ asyncio.run(main())
120
+ ```
121
+
122
+ ## Core API Reference
123
+
124
+ ### Runtime Management
125
+
126
+ #### `boxlite.Boxlite`
127
+
128
+ The main runtime for creating and managing boxes.
129
+
130
+ **Methods:**
131
+
132
+ - `Boxlite.default() -> Boxlite`
133
+ Create runtime with default settings (`~/.boxlite`)
134
+
135
+ - `Boxlite(options: Options) -> Boxlite`
136
+ Create runtime with custom options
137
+
138
+ - `create(box_options: BoxOptions) -> Box`
139
+ Create a new box with specified configuration
140
+
141
+ - `get(box_id: str) -> Box`
142
+ Reattach to an existing box by ID
143
+
144
+ - `list() -> List[BoxInfo]`
145
+ List all boxes (running and stopped)
146
+
147
+ - `metrics() -> RuntimeMetrics`
148
+ Get runtime-wide metrics
149
+
150
+ **Example:**
151
+
152
+ ```python
153
+ # Default runtime
154
+ runtime = boxlite.Boxlite.default()
155
+
156
+ # Custom runtime with different home directory
157
+ runtime = boxlite.Boxlite(boxlite.Options(home_dir="/custom/path"))
158
+
159
+ # Create a box
160
+ box = runtime.create(boxlite.BoxOptions(image="alpine:latest"))
161
+
162
+ # Reattach to existing box
163
+ box = runtime.get("01JJNH8...")
164
+
165
+ # List all boxes
166
+ boxes = runtime.list()
167
+ for info in boxes:
168
+ print(f"{info.id}: {info.status}")
169
+ ```
170
+
171
+ ### Box Configuration
172
+
173
+ #### `boxlite.BoxOptions`
174
+
175
+ Configuration options for creating a box.
176
+
177
+ **Parameters:**
178
+
179
+ - `image: str` - OCI image URI (default: `"python:slim"`)
180
+ - `cpus: int` - Number of CPUs (default: 1, max: host CPU count)
181
+ - `memory_mib: int` - Memory in MiB (default: 512, range: 128-65536)
182
+ - `disk_size_gb: int | None` - Persistent disk size in GB (default: None)
183
+ - `working_dir: str` - Working directory in container (default: `"/root"`)
184
+ - `env: List[Tuple[str, str]]` - Environment variables as (key, value) pairs
185
+ - `volumes: List[Tuple[str, str, str]]` - Volume mounts as (host_path, guest_path, mode)
186
+ - Mode: `"ro"` (read-only) or `"rw"` (read-write)
187
+ - `ports: List[Tuple[int, int, str]]` - Port forwarding as (host_port, guest_port, protocol)
188
+ - Protocol: `"tcp"` or `"udp"`
189
+ - `auto_remove: bool` - Auto cleanup after stop (default: True)
190
+
191
+ **Example:**
192
+
193
+ ```python
194
+ options = boxlite.BoxOptions(
195
+ image="postgres:latest",
196
+ cpus=2,
197
+ memory_mib=1024,
198
+ disk_size_gb=10, # 10 GB persistent disk
199
+ env=[
200
+ ("POSTGRES_PASSWORD", "secret"),
201
+ ("POSTGRES_DB", "mydb"),
202
+ ],
203
+ volumes=[
204
+ ("/host/data", "/mnt/data", "ro"), # Read-only mount
205
+ ],
206
+ ports=[
207
+ (5432, 5432, "tcp"), # PostgreSQL
208
+ ],
209
+ )
210
+ box = runtime.create(options)
211
+ ```
212
+
213
+ ### Box Handle
214
+
215
+ #### `boxlite.Box`
216
+
217
+ Handle to a running or stopped box.
218
+
219
+ **Properties:**
220
+
221
+ - `id: str` - Unique box identifier (ULID format)
222
+
223
+ **Methods:**
224
+
225
+ - `exec(*args, **kwargs) -> Execution`
226
+ Execute a command in the box (async)
227
+
228
+ - `stop() -> None`
229
+ Stop the box gracefully (async)
230
+
231
+ - `remove() -> None`
232
+ Delete the box and its data (async)
233
+
234
+ - `info() -> BoxInfo`
235
+ Get box metadata (async)
236
+
237
+ - `metrics() -> BoxMetrics`
238
+ Get box resource usage metrics (async)
239
+
240
+ **Example:**
241
+
242
+ ```python
243
+ box = runtime.create(boxlite.BoxOptions(image="alpine:latest"))
244
+
245
+ # Execute commands
246
+ execution = await box.exec("echo", "Hello")
247
+ result = await execution.wait()
248
+
249
+ # Get box info
250
+ info = await box.info()
251
+ print(f"Box {info.id}: {info.status}")
252
+
253
+ # Stop and remove
254
+ await box.stop()
255
+ await box.remove()
256
+ ```
257
+
258
+ ### Command Execution
259
+
260
+ #### `boxlite.Execution`
261
+
262
+ Represents a running command execution.
263
+
264
+ **Methods:**
265
+
266
+ - `stdout() -> ExecStdout`
267
+ Get stdout stream (async iterator)
268
+
269
+ - `stderr() -> ExecStderr`
270
+ Get stderr stream (async iterator)
271
+
272
+ - `stdin() -> ExecStdin`
273
+ Get stdin writer
274
+
275
+ - `wait() -> ExecResult`
276
+ Wait for command to complete and get result (async)
277
+
278
+ - `kill(signal: int = 9) -> None`
279
+ Send signal to process (async)
280
+
281
+ **Example:**
282
+
283
+ ```python
284
+ # Streaming output
285
+ execution = await box.exec("python", "-c", "for i in range(5): print(i)")
286
+
287
+ stdout = execution.stdout()
288
+ async for line in stdout:
289
+ print(f"Output: {line}")
290
+
291
+ # Wait for completion
292
+ result = await execution.wait()
293
+ print(f"Exit code: {result.exit_code}")
294
+ ```
295
+
296
+ #### `boxlite.ExecStdout` / `boxlite.ExecStderr`
297
+
298
+ Async iterators for streaming output.
299
+
300
+ **Usage:**
301
+
302
+ ```python
303
+ execution = await box.exec("ls", "-la")
304
+
305
+ # Stream stdout line by line
306
+ stdout = execution.stdout()
307
+ async for line in stdout:
308
+ print(line)
309
+
310
+ # Stream stderr
311
+ stderr = execution.stderr()
312
+ async for line in stderr:
313
+ print(f"Error: {line}", file=sys.stderr)
314
+ ```
315
+
316
+ ### Higher-Level APIs
317
+
318
+ #### `boxlite.SimpleBox`
319
+
320
+ Context manager for basic execution with automatic cleanup.
321
+
322
+ **Parameters:** Same as `BoxOptions`
323
+
324
+ **Methods:**
325
+
326
+ - `exec(*args, **kwargs) -> ExecResult`
327
+ Execute command and wait for result
328
+
329
+ **Example:**
330
+
331
+ ```python
332
+ async with boxlite.SimpleBox(image="python:slim") as box:
333
+ result = await box.exec("python", "-c", "print('Hello')")
334
+ print(result.stdout) # "Hello\n"
335
+ print(result.exit_code) # 0
336
+ ```
337
+
338
+ #### `boxlite.CodeBox`
339
+
340
+ Specialized box for Python code execution with package management.
341
+
342
+ **Methods:**
343
+
344
+ - `run(code: str) -> str`
345
+ Execute Python code and return output
346
+
347
+ - `install_package(package: str) -> None`
348
+ Install a Python package with pip
349
+
350
+ **Example:**
351
+
352
+ ```python
353
+ async with boxlite.CodeBox() as codebox:
354
+ # Install packages
355
+ await codebox.install_package("requests")
356
+
357
+ # Run code
358
+ result = await codebox.run("""
359
+ import requests
360
+ print(requests.get('https://api.github.com/zen').text)
361
+ """)
362
+ print(result)
363
+ ```
364
+
365
+ #### `boxlite.BrowserBox`
366
+
367
+ Box configured for browser automation (Chromium, Firefox, WebKit).
368
+
369
+ **Example:**
370
+
371
+ ```python
372
+ async with boxlite.BrowserBox() as browser:
373
+ endpoint = browser.endpoint()
374
+ print(f"Connect Puppeteer to: {endpoint}")
375
+ # Use with Puppeteer/Playwright for browser automation
376
+ ```
377
+
378
+ #### `boxlite.ComputerBox`
379
+
380
+ Box with desktop automation capabilities (mouse, keyboard, screenshots).
381
+
382
+ **Methods:**
383
+
384
+ 14 desktop interaction functions including:
385
+ - `screenshot() -> bytes` - Capture screen
386
+ - `left_click()` - Click mouse
387
+ - `type_text(text: str)` - Type text
388
+ - `get_screen_size() -> Tuple[int, int]` - Get screen dimensions
389
+
390
+ **Example:**
391
+
392
+ ```python
393
+ async with boxlite.ComputerBox() as computer:
394
+ # Get screen size
395
+ width, height = await computer.get_screen_size()
396
+
397
+ # Take screenshot
398
+ screenshot_bytes = await computer.screenshot()
399
+
400
+ # Mouse and keyboard
401
+ await computer.left_click()
402
+ await computer.type_text("Hello, world!")
403
+ ```
404
+
405
+ #### `boxlite.InteractiveBox`
406
+
407
+ Box for interactive shell sessions.
408
+
409
+ **Example:**
410
+
411
+ ```python
412
+ async with boxlite.InteractiveBox(image="alpine:latest") as itbox:
413
+ # Drop into interactive shell
414
+ await itbox.wait()
415
+ ```
416
+
417
+ ## API Patterns
418
+
419
+ ### Async/Await
420
+
421
+ All I/O operations are async. Use `await` for operations and `async for` for streams.
422
+
423
+ ```python
424
+ # Create and use box (async)
425
+ async with boxlite.SimpleBox(image="alpine") as box:
426
+ result = await box.exec("echo", "Hello")
427
+
428
+ # Stream output (async iterator)
429
+ execution = await box.exec("python", "script.py")
430
+ async for line in execution.stdout():
431
+ print(line)
432
+ ```
433
+
434
+ ### Context Managers
435
+
436
+ Use `async with` for automatic cleanup:
437
+
438
+ ```python
439
+ # SimpleBox - auto cleanup
440
+ async with boxlite.SimpleBox() as box:
441
+ result = await box.exec("command")
442
+ # Box automatically stopped and removed
443
+
444
+ # Manual cleanup (if not using context manager)
445
+ box = runtime.create(boxlite.BoxOptions(image="alpine"))
446
+ try:
447
+ await box.exec("command")
448
+ finally:
449
+ await box.stop()
450
+ await box.remove()
451
+ ```
452
+
453
+ ### Streaming I/O
454
+
455
+ Stream output line-by-line as it's produced:
456
+
457
+ ```python
458
+ execution = await box.exec("tail", "-f", "/var/log/app.log")
459
+
460
+ # Process output in real-time
461
+ stdout = execution.stdout()
462
+ async for line in stdout:
463
+ if "ERROR" in line:
464
+ print(f"Alert: {line}")
465
+ ```
466
+
467
+ ### Error Handling
468
+
469
+ Catch exceptions from BoxLite operations:
470
+
471
+ ```python
472
+ import boxlite
473
+ from boxlite import BoxliteError, ExecError
474
+
475
+ try:
476
+ async with boxlite.SimpleBox(image="invalid:image") as box:
477
+ result = await box.exec("command")
478
+ except BoxliteError as e:
479
+ print(f"BoxLite error: {e}")
480
+ except ExecError as e:
481
+ print(f"Execution error: {e}")
482
+ ```
483
+
484
+ ## Configuration Reference
485
+
486
+ ### Image Selection
487
+
488
+ Any OCI-compatible image from Docker Hub, GHCR, ECR, or other registries:
489
+
490
+ ```python
491
+ # Docker Hub (default registry)
492
+ boxlite.BoxOptions(image="python:3.11-slim")
493
+ boxlite.BoxOptions(image="alpine:latest")
494
+ boxlite.BoxOptions(image="ubuntu:22.04")
495
+
496
+ # GitHub Container Registry
497
+ boxlite.BoxOptions(image="ghcr.io/owner/repo:tag")
498
+
499
+ # Amazon ECR
500
+ boxlite.BoxOptions(image="123456.dkr.ecr.us-east-1.amazonaws.com/repo:tag")
501
+ ```
502
+
503
+ ### Resource Limits
504
+
505
+ ```python
506
+ boxlite.BoxOptions(
507
+ cpus=4, # 4 CPU cores
508
+ memory_mib=2048, # 2 GB RAM
509
+ )
510
+ ```
511
+
512
+ ### Environment Variables
513
+
514
+ ```python
515
+ boxlite.BoxOptions(
516
+ env=[
517
+ ("DATABASE_URL", "postgresql://localhost/db"),
518
+ ("API_KEY", "secret"),
519
+ ("DEBUG", "true"),
520
+ ]
521
+ )
522
+ ```
523
+
524
+ ### Volume Mounts
525
+
526
+ ```python
527
+ boxlite.BoxOptions(
528
+ volumes=[
529
+ # Read-only mount
530
+ ("/host/config", "/etc/app/config", "ro"),
531
+
532
+ # Read-write mount
533
+ ("/host/data", "/mnt/data", "rw"),
534
+ ]
535
+ )
536
+ ```
537
+
538
+ ### Port Forwarding
539
+
540
+ ```python
541
+ boxlite.BoxOptions(
542
+ ports=[
543
+ (8080, 80, "tcp"), # HTTP
544
+ (8443, 443, "tcp"), # HTTPS
545
+ (5432, 5432, "tcp"), # PostgreSQL
546
+ (53, 53, "udp"), # DNS
547
+ ]
548
+ )
549
+ ```
550
+
551
+ ### Persistent Storage
552
+
553
+ ```python
554
+ # Ephemeral (default) - data lost on box removal
555
+ boxlite.BoxOptions(image="postgres")
556
+
557
+ # Persistent - data survives stop/restart via QCOW2 disk
558
+ boxlite.BoxOptions(
559
+ image="postgres",
560
+ disk_size_gb=20, # 20 GB persistent disk
561
+ )
562
+ ```
563
+
564
+ ## Examples Gallery
565
+
566
+ The `examples/python/` directory contains 9 comprehensive examples:
567
+
568
+ ### 1. **simplebox_example.py** - Foundation Patterns
569
+ Demonstrates core BoxLite features:
570
+ - Basic command execution with results
571
+ - Separate stdout/stderr handling
572
+ - Environment variables and working directory
573
+ - Error handling and exit codes
574
+ - Multiple commands in same box
575
+ - Data processing pipeline
576
+
577
+ [View source](../../examples/python/simplebox_example.py)
578
+
579
+ ### 2. **codebox_example.py** - AI Code Execution
580
+ Secure Python code execution for AI agents:
581
+ - Basic code execution
582
+ - Dynamic package installation
583
+ - Data processing (AI agent use case)
584
+ - Isolation demonstration
585
+
586
+ [View source](../../examples/python/codebox_example.py)
587
+
588
+ ### 3. **browserbox_example.py** - Browser Automation
589
+ Browser automation with Puppeteer/Playwright:
590
+ - Basic Chromium setup
591
+ - Custom browser configurations (Firefox, WebKit)
592
+ - Cross-browser testing patterns
593
+ - Integration examples
594
+
595
+ [View source](../../examples/python/browserbox_example.py)
596
+
597
+ ### 4. **computerbox_example.py** - Desktop Automation
598
+ Desktop interaction for agent workflows:
599
+ - 14 desktop functions (mouse, keyboard, screenshots)
600
+ - Screen size detection
601
+ - Workflow automation
602
+ - GUI interaction patterns
603
+
604
+ [View source](../../examples/python/computerbox_example.py)
605
+
606
+ ### 5. **lifecycle_example.py** - Box Lifecycle Management
607
+ Managing box state:
608
+ - Stop and restart operations
609
+ - State persistence
610
+ - Data persistence verification
611
+ - Resource cleanup
612
+
613
+ [View source](../../examples/python/lifecycle_example.py)
614
+
615
+ ### 6. **list_boxes_example.py** - Runtime Introspection
616
+ Enumerate and inspect boxes:
617
+ - List all boxes with status
618
+ - Display box metadata (ID, name, state, resources)
619
+ - Filter by status
620
+
621
+ [View source](../../examples/python/list_boxes_example.py)
622
+
623
+ ### 7. **cross_process_example.py** - Multi-Process Operations
624
+ Cross-process box management:
625
+ - Reattach to running boxes from different processes
626
+ - Restart stopped boxes
627
+ - Multi-process runtime handling
628
+
629
+ [View source](../../examples/python/cross_process_example.py)
630
+
631
+ ### 8. **interactivebox_example.py** - Interactive Shells
632
+ Direct shell access:
633
+ - Interactive terminal sessions
634
+ - Terminal mode handling
635
+ - Simple container experience
636
+
637
+ [View source](../../examples/python/interactivebox_example.py)
638
+
639
+ ### 9. **native_example.py** - Low-Level API
640
+ Using the Rust API directly from Python:
641
+ - Default and custom runtime initialization
642
+ - Resource limits (CPU, memory, volumes, ports)
643
+ - Box information retrieval
644
+ - Streaming execution
645
+
646
+ [View source](../../examples/python/native_example.py)
647
+
648
+ ## Metrics & Monitoring
649
+
650
+ ### Runtime Metrics
651
+
652
+ Get aggregate metrics across all boxes:
653
+
654
+ ```python
655
+ runtime = boxlite.Boxlite.default()
656
+ metrics = runtime.metrics()
657
+
658
+ print(f"Boxes created: {metrics.boxes_created}")
659
+ print(f"Boxes destroyed: {metrics.boxes_destroyed}")
660
+ print(f"Total exec calls: {metrics.total_exec_calls}")
661
+ ```
662
+
663
+ **RuntimeMetrics Fields:**
664
+ - `boxes_created: int` - Total boxes created
665
+ - `boxes_destroyed: int` - Total boxes destroyed
666
+ - `total_exec_calls: int` - Total command executions
667
+ - `active_boxes: int` - Currently running boxes
668
+
669
+ ### Box Metrics
670
+
671
+ Get per-box resource usage:
672
+
673
+ ```python
674
+ box = runtime.create(boxlite.BoxOptions(image="alpine"))
675
+ metrics = await box.metrics()
676
+
677
+ print(f"CPU time: {metrics.cpu_time_ms}ms")
678
+ print(f"Memory: {metrics.memory_usage_bytes / (1024**2):.2f} MB")
679
+ print(f"Network sent: {metrics.network_bytes_sent}")
680
+ print(f"Network received: {metrics.network_bytes_received}")
681
+ ```
682
+
683
+ **BoxMetrics Fields:**
684
+ - `cpu_time_ms: int` - Total CPU time in milliseconds
685
+ - `memory_usage_bytes: int` - Current memory usage
686
+ - `network_bytes_sent: int` - Total bytes sent
687
+ - `network_bytes_received: int` - Total bytes received
688
+
689
+ ## Error Handling
690
+
691
+ ### Exception Types
692
+
693
+ ```python
694
+ from boxlite import BoxliteError, ExecError, TimeoutError, ParseError
695
+ ```
696
+
697
+ **BoxliteError** - Base exception for all BoxLite errors
698
+
699
+ **ExecError** - Command execution failed
700
+
701
+ **TimeoutError** - Operation timed out
702
+
703
+ **ParseError** - Failed to parse output
704
+
705
+ ### Common Error Patterns
706
+
707
+ ```python
708
+ import boxlite
709
+
710
+ async def safe_execution():
711
+ try:
712
+ async with boxlite.SimpleBox(image="python:slim") as box:
713
+ result = await box.exec("python", "script.py")
714
+
715
+ # Check exit code
716
+ if result.exit_code != 0:
717
+ print(f"Command failed: {result.stderr}")
718
+
719
+ except boxlite.BoxliteError as e:
720
+ # Handle BoxLite-specific errors
721
+ print(f"BoxLite error: {e}")
722
+ except Exception as e:
723
+ # Handle other errors
724
+ print(f"Unexpected error: {e}")
725
+ ```
726
+
727
+ ## Troubleshooting
728
+
729
+ ### Installation Issues
730
+
731
+ **Problem:** `pip install boxlite` fails
732
+
733
+ **Solutions:**
734
+ - Ensure Python 3.10+: `python --version`
735
+ - Update pip: `pip install --upgrade pip`
736
+ - Check platform support (macOS ARM64, Linux x86_64/ARM64 only)
737
+
738
+ ### Runtime Errors
739
+
740
+ **Problem:** "KVM not available" error on Linux
741
+
742
+ **Solutions:**
743
+ ```bash
744
+ # Check if KVM is loaded
745
+ lsmod | grep kvm
746
+
747
+ # Check if /dev/kvm exists
748
+ ls -l /dev/kvm
749
+
750
+ # Add user to kvm group (may require logout/login)
751
+ sudo usermod -aG kvm $USER
752
+ ```
753
+
754
+ **Problem:** "Hypervisor.framework not available" on macOS
755
+
756
+ **Solutions:**
757
+ - Ensure macOS 12+ (Monterey or later)
758
+ - Verify Apple Silicon (ARM64) - Intel Macs not supported
759
+ - Check System Settings → Privacy & Security → Developer Tools
760
+
761
+ ### Image Pull Failures
762
+
763
+ **Problem:** "Failed to pull image" error
764
+
765
+ **Solutions:**
766
+ - Check internet connectivity
767
+ - Verify image name and tag exist: `docker pull <image>`
768
+ - For private images, authenticate with registry first
769
+
770
+ ### Performance Issues
771
+
772
+ **Problem:** Box is slow or unresponsive
773
+
774
+ **Solutions:**
775
+ ```python
776
+ # Increase resource limits
777
+ boxlite.BoxOptions(
778
+ cpus=4, # More CPUs
779
+ memory_mib=4096, # More memory
780
+ )
781
+
782
+ # Check metrics
783
+ metrics = await box.metrics()
784
+ print(f"Memory usage: {metrics.memory_usage_bytes / (1024**2):.2f} MB")
785
+ print(f"CPU time: {metrics.cpu_time_ms}ms")
786
+ ```
787
+
788
+ ### Debug Logging
789
+
790
+ Enable debug logging to troubleshoot issues:
791
+
792
+ ```bash
793
+ # Set RUST_LOG environment variable
794
+ RUST_LOG=debug python script.py
795
+ ```
796
+
797
+ Log levels: `trace`, `debug`, `info`, `warn`, `error`
798
+
799
+ ## Contributing
800
+
801
+ We welcome contributions to the Python SDK!
802
+
803
+ ### Development Setup
804
+
805
+ ```bash
806
+ # Clone repository
807
+ git clone https://github.com/boxlite-labs/boxlite.git
808
+ cd boxlite
809
+
810
+ # Initialize submodules
811
+ git submodule update --init --recursive
812
+
813
+ # Build Python SDK in development mode
814
+ make dev:python
815
+ ```
816
+
817
+ ### Running Tests
818
+
819
+ ```bash
820
+ # Install dev dependencies
821
+ pip install -e ".[dev]"
822
+
823
+ # Run tests
824
+ python -m pytest sdks/python/tests/
825
+ ```
826
+
827
+ ### Building Wheels
828
+
829
+ ```bash
830
+ # Build portable wheel
831
+ make dist:python
832
+ ```
833
+
834
+ ## Further Documentation
835
+
836
+ - [BoxLite Main README](../../README.md) - Project overview
837
+ - [Architecture Documentation](../../docs/architecture/README.md) - How BoxLite works
838
+ - [Getting Started Guide](../../docs/getting-started/README.md) - Installation and setup
839
+ - [How-to Guides](../../docs/guides/README.md) - Practical guides
840
+ - [API Reference](../../docs/reference/README.md) - Complete API documentation
841
+
842
+ ## License
843
+
844
+ Licensed under the Apache License, Version 2.0. See [LICENSE](../../LICENSE) for details.
845
+