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 ("\n Result 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"\n Exit 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 ("\n Example 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 ("\n All 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 \n Demo interrupted by user. Goodbye!" )
0 commit comments