Runs a shell command in a 'with' context. This implementation is Win32-specific. Example: # Runs the command interactively with default console stdin/stdout with ShellCommandController('python -i') as scc: scc.run() # Runs the command using the provided
| 188 | |
| 189 | |
| 190 | class Win32ShellCommandController: |
| 191 | """Runs a shell command in a 'with' context. |
| 192 | |
| 193 | This implementation is Win32-specific. |
| 194 | |
| 195 | Example: |
| 196 | # Runs the command interactively with default console stdin/stdout |
| 197 | with ShellCommandController('python -i') as scc: |
| 198 | scc.run() |
| 199 | |
| 200 | # Runs the command using the provided functions for stdin/stdout |
| 201 | def my_stdout_func(s): |
| 202 | # print or save the string 's' |
| 203 | write_to_stdout(s) |
| 204 | def my_stdin_func(): |
| 205 | # If input is available, return it as a string. |
| 206 | if input_available(): |
| 207 | return get_input() |
| 208 | # If no input available, return None after a short delay to |
| 209 | # keep from blocking. |
| 210 | else: |
| 211 | time.sleep(0.01) |
| 212 | return None |
| 213 | |
| 214 | with ShellCommandController('python -i') as scc: |
| 215 | scc.run(my_stdout_func, my_stdin_func) |
| 216 | """ |
| 217 | |
| 218 | def __init__(self, cmd, mergeout = True): |
| 219 | """Initializes the shell command controller. |
| 220 | |
| 221 | The cmd is the program to execute, and mergeout is |
| 222 | whether to blend stdout and stderr into one output |
| 223 | in stdout. Merging them together in this fashion more |
| 224 | reliably keeps stdout and stderr in the correct order |
| 225 | especially for interactive shell usage. |
| 226 | """ |
| 227 | self.cmd = cmd |
| 228 | self.mergeout = mergeout |
| 229 | |
| 230 | def __enter__(self): |
| 231 | cmd = self.cmd |
| 232 | mergeout = self.mergeout |
| 233 | |
| 234 | self.hstdout, self.hstdin, self.hstderr = None, None, None |
| 235 | self.piProcInfo = None |
| 236 | try: |
| 237 | p_hstdout, c_hstdout, p_hstderr, \ |
| 238 | c_hstderr, p_hstdin, c_hstdin = [None]*6 |
| 239 | |
| 240 | # SECURITY_ATTRIBUTES with inherit handle set to True |
| 241 | saAttr = SECURITY_ATTRIBUTES() |
| 242 | saAttr.nLength = ctypes.sizeof(saAttr) |
| 243 | saAttr.bInheritHandle = True |
| 244 | saAttr.lpSecurityDescriptor = None |
| 245 | |
| 246 | def create_pipe(uninherit): |
| 247 | """Creates a Windows pipe, which consists of two handles. |
no outgoing calls
no test coverage detected
searching dependent graphs…