Skip to content

Commit 28acec2

Browse files
dugshubclaude
andcommitted
feat: add interactive demo scripts for SubprocessExecutor (CLI-9)
- Created comprehensive interactive demo showing all SubprocessExecutor features - Added explanations before each command execution - Implemented user command mode with customizable timeout and environment - Demonstrated concurrent execution, error handling, and output streaming - Added non-interactive test script for quick validation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 3dc223e commit 28acec2

File tree

2 files changed

+248
-0
lines changed

2 files changed

+248
-0
lines changed

examples/subprocess_demo.py

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
#!/usr/bin/env python3
2+
"""Interactive demo script showing SubprocessExecutor functionality."""
3+
4+
import asyncio
5+
import sys
6+
from rich.console import Console
7+
from rich.prompt import Prompt, Confirm
8+
from rich.panel import Panel
9+
from rich.text import Text
10+
from cli_patterns.execution.subprocess_executor import SubprocessExecutor
11+
12+
13+
def wait_for_enter(message="Press Enter to continue..."):
14+
"""Wait for user to press enter."""
15+
input(f"\n{message}")
16+
17+
18+
async def run_example(executor, title, explanation, command, **kwargs):
19+
"""Run an example command with title and wait for user."""
20+
print(f"\n{title}")
21+
print(f"What this will do: {explanation}")
22+
print(f"Command: {command}")
23+
print("-" * 50)
24+
25+
result = await executor.run(command, **kwargs)
26+
27+
print("\nResult Summary:")
28+
print(f" Exit code: {result.exit_code}")
29+
print(f" Success: {result.success}")
30+
if result.timed_out:
31+
print(f" Timed out: True")
32+
if result.interrupted:
33+
print(f" Interrupted: True")
34+
if result.stderr and not result.success:
35+
print(f" Error: {result.stderr[:100]}...")
36+
37+
wait_for_enter()
38+
return result
39+
40+
41+
async def user_command_loop(executor, console):
42+
"""Allow user to run custom commands."""
43+
console.print(Panel.fit(
44+
"[bold cyan]Interactive Command Mode[/bold cyan]\n"
45+
"Enter commands to run them with the SubprocessExecutor.\n"
46+
"Type 'exit' or 'quit' to leave.",
47+
border_style="cyan"
48+
))
49+
50+
while True:
51+
print()
52+
command = Prompt.ask("[bold green]Enter command[/bold green]", default="exit")
53+
54+
if command.lower() in ['exit', 'quit']:
55+
break
56+
57+
# Ask for optional parameters
58+
use_timeout = Confirm.ask("Set a custom timeout?", default=False)
59+
timeout = None
60+
if use_timeout:
61+
timeout = float(Prompt.ask("Timeout (seconds)", default="30"))
62+
63+
use_env = Confirm.ask("Add environment variables?", default=False)
64+
env = None
65+
if use_env:
66+
env_vars = {}
67+
console.print("[dim]Enter variables as KEY=VALUE, empty to finish[/dim]")
68+
while True:
69+
var = Prompt.ask("Environment variable", default="")
70+
if not var:
71+
break
72+
if '=' in var:
73+
key, value = var.split('=', 1)
74+
env_vars[key] = value
75+
if env_vars:
76+
env = env_vars
77+
78+
print("\n" + "=" * 50)
79+
print(f"What this will do: Execute '{command}'")
80+
if timeout:
81+
print(f" with timeout of {timeout} seconds")
82+
if env:
83+
print(f" with environment variables: {env}")
84+
print("Executing now...")
85+
print("=" * 50)
86+
result = await executor.run(command, timeout=timeout, env=env)
87+
print("=" * 50)
88+
89+
print(f"\nExit code: {result.exit_code}")
90+
print(f"Success: {result.success}")
91+
92+
if result.stdout:
93+
show_output = Confirm.ask("Show full stdout?", default=True)
94+
if show_output:
95+
console.print(Panel(result.stdout, title="stdout", border_style="green"))
96+
97+
if result.stderr:
98+
console.print(Panel(result.stderr, title="stderr", border_style="red"))
99+
100+
101+
async def main():
102+
"""Run subprocess executor demonstrations."""
103+
console = Console()
104+
executor = SubprocessExecutor(console=console)
105+
106+
console.print(Panel.fit(
107+
Text("SubprocessExecutor Interactive Demo", justify="center", style="bold magenta"),
108+
subtitle="Learn how CLI-9 works",
109+
border_style="magenta"
110+
))
111+
112+
console.print("\n[bold]This demo will show you:[/bold]")
113+
console.print("• Running successful commands")
114+
console.print("• Handling command failures")
115+
console.print("• Timeout management")
116+
console.print("• Output capture")
117+
console.print("• Custom environments")
118+
console.print("• Concurrent execution")
119+
console.print("• Interactive command mode\n")
120+
121+
wait_for_enter("Press Enter to start the demo...")
122+
123+
# Example 1: Simple successful command
124+
await run_example(
125+
executor,
126+
"Example 1: Running a successful command",
127+
"List the first 5 files in the current directory with details",
128+
"ls -la | head -5"
129+
)
130+
131+
# Example 2: Command that fails
132+
await run_example(
133+
executor,
134+
"Example 2: Running a command that fails",
135+
"Attempt to list a directory that doesn't exist to see error handling",
136+
"ls /nonexistent/directory"
137+
)
138+
139+
# Example 3: Command with timeout
140+
await run_example(
141+
executor,
142+
"Example 3: Running a command with timeout (1 second)",
143+
"Run a 5-second sleep command but timeout after 1 second",
144+
"sleep 5",
145+
timeout=1.0
146+
)
147+
148+
# Example 4: Capturing output
149+
await run_example(
150+
executor,
151+
"Example 4: Capturing command output",
152+
"Echo a message and capture its output for programmatic use",
153+
"echo 'Hello from subprocess!'"
154+
)
155+
156+
# Example 5: Running with custom environment
157+
await run_example(
158+
executor,
159+
"Example 5: Running with custom environment variable",
160+
"Set a custom environment variable and echo its value",
161+
"echo 'MY_CUSTOM_VAR=$MY_CUSTOM_VAR'",
162+
env={"MY_CUSTOM_VAR": "Custom Value!"}
163+
)
164+
165+
# Example 6: Running multiple commands concurrently
166+
print("\nExample 6: Running multiple commands concurrently")
167+
print("What this will do: Execute 3 commands in parallel with different sleep times")
168+
print("Expected behavior: All tasks start together, finish at different times")
169+
print("Commands: Three echo commands with different delays")
170+
print("-" * 50)
171+
172+
tasks = [
173+
executor.run("echo 'Task 1 running' && sleep 0.5 && echo 'Task 1 done'"),
174+
executor.run("echo 'Task 2 running' && sleep 0.3 && echo 'Task 2 done'"),
175+
executor.run("echo 'Task 3 running' && sleep 0.1 && echo 'Task 3 done'"),
176+
]
177+
178+
console.print("[yellow]Starting 3 parallel tasks...[/yellow]")
179+
results = await asyncio.gather(*tasks)
180+
181+
print("\nAll tasks completed!")
182+
for i, result in enumerate(results, 1):
183+
lines = result.stdout.strip().split('\n')
184+
print(f" Task {i}: {lines[-1] if lines else 'No output'}")
185+
186+
wait_for_enter()
187+
188+
# Interactive mode
189+
console.print("\n[bold yellow]Ready to try your own commands?[/bold yellow]")
190+
if Confirm.ask("Enter interactive mode?", default=True):
191+
await user_command_loop(executor, console)
192+
193+
console.print(Panel.fit(
194+
"[bold green]Demo Complete![/bold green]\n"
195+
"You've learned how the SubprocessExecutor works.\n"
196+
"Use it in your CLI patterns for async command execution.",
197+
border_style="green"
198+
))
199+
200+
201+
if __name__ == "__main__":
202+
try:
203+
asyncio.run(main())
204+
except KeyboardInterrupt:
205+
print("\n\nDemo interrupted by user. Goodbye!")

examples/subprocess_test.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env python3
2+
"""Quick test of SubprocessExecutor's interactive features."""
3+
4+
import asyncio
5+
from rich.console import Console
6+
from cli_patterns.execution.subprocess_executor import SubprocessExecutor
7+
8+
9+
async def main():
10+
"""Test custom commands with SubprocessExecutor."""
11+
console = Console()
12+
executor = SubprocessExecutor(console=console)
13+
14+
# Test a few custom commands
15+
commands = [
16+
("pwd", None, None),
17+
("echo 'Testing custom command'", None, None),
18+
("ls -la | grep examples", None, None),
19+
("date", None, None),
20+
("echo 'VAR is: $TEST_VAR'", None, {"TEST_VAR": "Hello World!"}),
21+
("python3 -c 'print(\"Python says hello!\")'", None, None),
22+
]
23+
24+
for cmd, timeout, env in commands:
25+
print(f"\n{'='*60}")
26+
print(f"Running: {cmd}")
27+
if env:
28+
print(f"With env: {env}")
29+
print('='*60)
30+
31+
result = await executor.run(cmd, timeout=timeout, env=env)
32+
33+
print(f"\nResult:")
34+
print(f" Exit code: {result.exit_code}")
35+
print(f" Success: {result.success}")
36+
if result.stdout:
37+
print(f" Output: {result.stdout.strip()}")
38+
if result.stderr:
39+
print(f" Error: {result.stderr.strip()}")
40+
41+
42+
if __name__ == "__main__":
43+
asyncio.run(main())

0 commit comments

Comments
 (0)