Show More
@@ -0,0 +1,264 b'' | |||
|
1 | # A module to expose various thread/process/job related structures and | |
|
2 | # methods from kernel32 | |
|
3 | # | |
|
4 | # The MIT License | |
|
5 | # | |
|
6 | # Copyright (c) 2006 the Mozilla Foundation <http://www.mozilla.org> | |
|
7 | # | |
|
8 | # Permission is hereby granted, free of charge, to any person obtaining a | |
|
9 | # copy of this software and associated documentation files (the "Software"), | |
|
10 | # to deal in the Software without restriction, including without limitation | |
|
11 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
|
12 | # and/or sell copies of the Software, and to permit persons to whom the | |
|
13 | # Software is furnished to do so, subject to the following conditions: | |
|
14 | # | |
|
15 | # The above copyright notice and this permission notice shall be included in | |
|
16 | # all copies or substantial portions of the Software. | |
|
17 | # | |
|
18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
|
19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
|
20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
|
21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
|
22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
|
23 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
|
24 | # DEALINGS IN THE SOFTWARE. | |
|
25 | ||
|
26 | from ctypes import c_void_p, POINTER, sizeof, Structure, windll, WinError, WINFUNCTYPE | |
|
27 | from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LPCWSTR, LPWSTR, UINT, WORD | |
|
28 | ||
|
29 | LPVOID = c_void_p | |
|
30 | LPBYTE = POINTER(BYTE) | |
|
31 | LPDWORD = POINTER(DWORD) | |
|
32 | ||
|
33 | SW_HIDE = 0 | |
|
34 | ||
|
35 | def ErrCheckBool(result, func, args): | |
|
36 | """errcheck function for Windows functions that return a BOOL True | |
|
37 | on success""" | |
|
38 | if not result: | |
|
39 | raise WinError() | |
|
40 | return args | |
|
41 | ||
|
42 | # CloseHandle() | |
|
43 | ||
|
44 | CloseHandleProto = WINFUNCTYPE(BOOL, HANDLE) | |
|
45 | CloseHandle = CloseHandleProto(("CloseHandle", windll.kernel32)) | |
|
46 | CloseHandle.errcheck = ErrCheckBool | |
|
47 | ||
|
48 | # AutoHANDLE | |
|
49 | ||
|
50 | class AutoHANDLE(HANDLE): | |
|
51 | """Subclass of HANDLE which will call CloseHandle() on deletion.""" | |
|
52 | def Close(self): | |
|
53 | if self.value: | |
|
54 | CloseHandle(self) | |
|
55 | self.value = 0 | |
|
56 | ||
|
57 | def __del__(self): | |
|
58 | self.Close() | |
|
59 | ||
|
60 | def __int__(self): | |
|
61 | return self.value | |
|
62 | ||
|
63 | def ErrCheckHandle(result, func, args): | |
|
64 | """errcheck function for Windows functions that return a HANDLE.""" | |
|
65 | if not result: | |
|
66 | raise WinError() | |
|
67 | return AutoHANDLE(result) | |
|
68 | ||
|
69 | # PROCESS_INFORMATION structure | |
|
70 | ||
|
71 | class PROCESS_INFORMATION(Structure): | |
|
72 | _fields_ = [("hProcess", HANDLE), | |
|
73 | ("hThread", HANDLE), | |
|
74 | ("dwProcessID", DWORD), | |
|
75 | ("dwThreadID", DWORD)] | |
|
76 | ||
|
77 | def __init__(self): | |
|
78 | Structure.__init__(self) | |
|
79 | ||
|
80 | self.cb = sizeof(self) | |
|
81 | ||
|
82 | LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION) | |
|
83 | ||
|
84 | # STARTUPINFO structure | |
|
85 | ||
|
86 | class STARTUPINFO(Structure): | |
|
87 | _fields_ = [("cb", DWORD), | |
|
88 | ("lpReserved", LPWSTR), | |
|
89 | ("lpDesktop", LPWSTR), | |
|
90 | ("lpTitle", LPWSTR), | |
|
91 | ("dwX", DWORD), | |
|
92 | ("dwY", DWORD), | |
|
93 | ("dwXSize", DWORD), | |
|
94 | ("dwYSize", DWORD), | |
|
95 | ("dwXCountChars", DWORD), | |
|
96 | ("dwYCountChars", DWORD), | |
|
97 | ("dwFillAttribute", DWORD), | |
|
98 | ("dwFlags", DWORD), | |
|
99 | ("wShowWindow", WORD), | |
|
100 | ("cbReserved2", WORD), | |
|
101 | ("lpReserved2", LPBYTE), | |
|
102 | ("hStdInput", HANDLE), | |
|
103 | ("hStdOutput", HANDLE), | |
|
104 | ("hStdError", HANDLE) | |
|
105 | ] | |
|
106 | LPSTARTUPINFO = POINTER(STARTUPINFO) | |
|
107 | ||
|
108 | STARTF_USESHOWWINDOW = 0x01 | |
|
109 | STARTF_USESIZE = 0x02 | |
|
110 | STARTF_USEPOSITION = 0x04 | |
|
111 | STARTF_USECOUNTCHARS = 0x08 | |
|
112 | STARTF_USEFILLATTRIBUTE = 0x10 | |
|
113 | STARTF_RUNFULLSCREEN = 0x20 | |
|
114 | STARTF_FORCEONFEEDBACK = 0x40 | |
|
115 | STARTF_FORCEOFFFEEDBACK = 0x80 | |
|
116 | STARTF_USESTDHANDLES = 0x100 | |
|
117 | ||
|
118 | # EnvironmentBlock | |
|
119 | ||
|
120 | class EnvironmentBlock: | |
|
121 | """An object which can be passed as the lpEnv parameter of CreateProcess. | |
|
122 | It is initialized with a dictionary.""" | |
|
123 | ||
|
124 | def __init__(self, dict): | |
|
125 | if not dict: | |
|
126 | self._as_parameter_ = None | |
|
127 | else: | |
|
128 | values = ["%s=%s" % (key, value) | |
|
129 | for (key, value) in dict.iteritems()] | |
|
130 | values.append("") | |
|
131 | self._as_parameter_ = LPCWSTR("\0".join(values)) | |
|
132 | ||
|
133 | # CreateProcess() | |
|
134 | ||
|
135 | CreateProcessProto = WINFUNCTYPE(BOOL, # Return type | |
|
136 | LPCWSTR, # lpApplicationName | |
|
137 | LPWSTR, # lpCommandLine | |
|
138 | LPVOID, # lpProcessAttributes | |
|
139 | LPVOID, # lpThreadAttributes | |
|
140 | BOOL, # bInheritHandles | |
|
141 | DWORD, # dwCreationFlags | |
|
142 | LPVOID, # lpEnvironment | |
|
143 | LPCWSTR, # lpCurrentDirectory | |
|
144 | LPSTARTUPINFO, # lpStartupInfo | |
|
145 | LPPROCESS_INFORMATION # lpProcessInformation | |
|
146 | ) | |
|
147 | ||
|
148 | CreateProcessFlags = ((1, "lpApplicationName", None), | |
|
149 | (1, "lpCommandLine"), | |
|
150 | (1, "lpProcessAttributes", None), | |
|
151 | (1, "lpThreadAttributes", None), | |
|
152 | (1, "bInheritHandles", True), | |
|
153 | (1, "dwCreationFlags", 0), | |
|
154 | (1, "lpEnvironment", None), | |
|
155 | (1, "lpCurrentDirectory", None), | |
|
156 | (1, "lpStartupInfo"), | |
|
157 | (2, "lpProcessInformation")) | |
|
158 | ||
|
159 | def ErrCheckCreateProcess(result, func, args): | |
|
160 | ErrCheckBool(result, func, args) | |
|
161 | # return a tuple (hProcess, hThread, dwProcessID, dwThreadID) | |
|
162 | pi = args[9] | |
|
163 | return AutoHANDLE(pi.hProcess), AutoHANDLE(pi.hThread), pi.dwProcessID, pi.dwThreadID | |
|
164 | ||
|
165 | CreateProcess = CreateProcessProto(("CreateProcessW", windll.kernel32), | |
|
166 | CreateProcessFlags) | |
|
167 | CreateProcess.errcheck = ErrCheckCreateProcess | |
|
168 | ||
|
169 | CREATE_BREAKAWAY_FROM_JOB = 0x01000000 | |
|
170 | CREATE_DEFAULT_ERROR_MODE = 0x04000000 | |
|
171 | CREATE_NEW_CONSOLE = 0x00000010 | |
|
172 | CREATE_NEW_PROCESS_GROUP = 0x00000200 | |
|
173 | CREATE_NO_WINDOW = 0x08000000 | |
|
174 | CREATE_SUSPENDED = 0x00000004 | |
|
175 | CREATE_UNICODE_ENVIRONMENT = 0x00000400 | |
|
176 | DEBUG_ONLY_THIS_PROCESS = 0x00000002 | |
|
177 | DEBUG_PROCESS = 0x00000001 | |
|
178 | DETACHED_PROCESS = 0x00000008 | |
|
179 | ||
|
180 | # CreateJobObject() | |
|
181 | ||
|
182 | CreateJobObjectProto = WINFUNCTYPE(HANDLE, # Return type | |
|
183 | LPVOID, # lpJobAttributes | |
|
184 | LPCWSTR # lpName | |
|
185 | ) | |
|
186 | ||
|
187 | CreateJobObjectFlags = ((1, "lpJobAttributes", None), | |
|
188 | (1, "lpName", None)) | |
|
189 | ||
|
190 | CreateJobObject = CreateJobObjectProto(("CreateJobObjectW", windll.kernel32), | |
|
191 | CreateJobObjectFlags) | |
|
192 | CreateJobObject.errcheck = ErrCheckHandle | |
|
193 | ||
|
194 | # AssignProcessToJobObject() | |
|
195 | ||
|
196 | AssignProcessToJobObjectProto = WINFUNCTYPE(BOOL, # Return type | |
|
197 | HANDLE, # hJob | |
|
198 | HANDLE # hProcess | |
|
199 | ) | |
|
200 | AssignProcessToJobObjectFlags = ((1, "hJob"), | |
|
201 | (1, "hProcess")) | |
|
202 | AssignProcessToJobObject = AssignProcessToJobObjectProto( | |
|
203 | ("AssignProcessToJobObject", windll.kernel32), | |
|
204 | AssignProcessToJobObjectFlags) | |
|
205 | AssignProcessToJobObject.errcheck = ErrCheckBool | |
|
206 | ||
|
207 | # ResumeThread() | |
|
208 | ||
|
209 | def ErrCheckResumeThread(result, func, args): | |
|
210 | if result == -1: | |
|
211 | raise WinError() | |
|
212 | ||
|
213 | return args | |
|
214 | ||
|
215 | ResumeThreadProto = WINFUNCTYPE(DWORD, # Return type | |
|
216 | HANDLE # hThread | |
|
217 | ) | |
|
218 | ResumeThreadFlags = ((1, "hThread"),) | |
|
219 | ResumeThread = ResumeThreadProto(("ResumeThread", windll.kernel32), | |
|
220 | ResumeThreadFlags) | |
|
221 | ResumeThread.errcheck = ErrCheckResumeThread | |
|
222 | ||
|
223 | # TerminateJobObject() | |
|
224 | ||
|
225 | TerminateJobObjectProto = WINFUNCTYPE(BOOL, # Return type | |
|
226 | HANDLE, # hJob | |
|
227 | UINT # uExitCode | |
|
228 | ) | |
|
229 | TerminateJobObjectFlags = ((1, "hJob"), | |
|
230 | (1, "uExitCode", 127)) | |
|
231 | TerminateJobObject = TerminateJobObjectProto( | |
|
232 | ("TerminateJobObject", windll.kernel32), | |
|
233 | TerminateJobObjectFlags) | |
|
234 | TerminateJobObject.errcheck = ErrCheckBool | |
|
235 | ||
|
236 | # WaitForSingleObject() | |
|
237 | ||
|
238 | WaitForSingleObjectProto = WINFUNCTYPE(DWORD, # Return type | |
|
239 | HANDLE, # hHandle | |
|
240 | DWORD, # dwMilliseconds | |
|
241 | ) | |
|
242 | WaitForSingleObjectFlags = ((1, "hHandle"), | |
|
243 | (1, "dwMilliseconds", -1)) | |
|
244 | WaitForSingleObject = WaitForSingleObjectProto( | |
|
245 | ("WaitForSingleObject", windll.kernel32), | |
|
246 | WaitForSingleObjectFlags) | |
|
247 | ||
|
248 | INFINITE = -1 | |
|
249 | WAIT_TIMEOUT = 0x0102 | |
|
250 | WAIT_OBJECT_0 = 0x0 | |
|
251 | WAIT_ABANDONED = 0x0080 | |
|
252 | ||
|
253 | # GetExitCodeProcess() | |
|
254 | ||
|
255 | GetExitCodeProcessProto = WINFUNCTYPE(BOOL, # Return type | |
|
256 | HANDLE, # hProcess | |
|
257 | LPDWORD, # lpExitCode | |
|
258 | ) | |
|
259 | GetExitCodeProcessFlags = ((1, "hProcess"), | |
|
260 | (2, "lpExitCode")) | |
|
261 | GetExitCodeProcess = GetExitCodeProcessProto( | |
|
262 | ("GetExitCodeProcess", windll.kernel32), | |
|
263 | GetExitCodeProcessFlags) | |
|
264 | GetExitCodeProcess.errcheck = ErrCheckBool |
@@ -107,7 +107,7 b' class Popen(subprocess.Popen):' | |||
|
107 | 107 | |
|
108 | 108 | if startupinfo is None: |
|
109 | 109 | startupinfo = winprocess.STARTUPINFO() |
|
110 | ||
|
110 | ||
|
111 | 111 | if None not in (p2cread, c2pwrite, errwrite): |
|
112 | 112 | startupinfo.dwFlags |= winprocess.STARTF_USESTDHANDLES |
|
113 | 113 |
@@ -194,7 +194,7 b' class ConsoleWidget(editwindow.EditWindow):' | |||
|
194 | 194 | self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment']) |
|
195 | 195 | |
|
196 | 196 | |
|
197 | def write(self, text): | |
|
197 | def write(self, text, refresh=True): | |
|
198 | 198 | """ Write given text to buffer, while translating the ansi escape |
|
199 | 199 | sequences. |
|
200 | 200 | """ |
@@ -227,7 +227,8 b' class ConsoleWidget(editwindow.EditWindow):' | |||
|
227 | 227 | self.SetStyling(len(text), style) |
|
228 | 228 | |
|
229 | 229 | self.GotoPos(self.GetLength()) |
|
230 | wx.Yield() | |
|
230 | if refresh: | |
|
231 | wx.Yield() | |
|
231 | 232 | |
|
232 | 233 | |
|
233 | 234 | def new_prompt(self, prompt): |
@@ -21,7 +21,7 b' class IPythonXController(WxController):' | |||
|
21 | 21 | # Intercept Ctrl-D to quit |
|
22 | 22 | if event.KeyCode == ord('D') and event.ControlDown() and \ |
|
23 | 23 | self.get_current_edit_buffer()=='' and \ |
|
24 |
|
|
|
24 | self._input_state == 'readline': | |
|
25 | 25 | wx.CallAfter(self.ask_exit) |
|
26 | 26 | else: |
|
27 | 27 | WxController._on_key_down(self, event, skip=skip) |
@@ -257,7 +257,7 b' class WxController(PrefilterFrontEnd, ConsoleWidget):' | |||
|
257 | 257 | self._out_buffer.append(text) |
|
258 | 258 | self._out_buffer_lock.release() |
|
259 | 259 | if not self._buffer_flush_timer.IsRunning(): |
|
260 |
self._buffer_flush_timer.Start |
|
|
260 | wx.CallAfter(self._buffer_flush_timer.Start, 100) # milliseconds | |
|
261 | 261 | |
|
262 | 262 | |
|
263 | 263 | def show_traceback(self): |
@@ -297,6 +297,7 b' class WxController(PrefilterFrontEnd, ConsoleWidget):' | |||
|
297 | 297 | if self.debug: |
|
298 | 298 | print >>sys.__stderr__, chr(event.KeyCode) |
|
299 | 299 | self._running_process.process.stdin.write(chr(event.KeyCode)) |
|
300 | self._running_process.process.stdin.flush() | |
|
300 | 301 | elif event.KeyCode in (ord('('), 57): |
|
301 | 302 | # Calltips |
|
302 | 303 | event.Skip() |
@@ -372,7 +373,7 b' class WxController(PrefilterFrontEnd, ConsoleWidget):' | |||
|
372 | 373 | _out_buffer = self._out_buffer |
|
373 | 374 | self._out_buffer = [] |
|
374 | 375 | self._out_buffer_lock.release() |
|
375 | self.write(''.join(_out_buffer)) | |
|
376 | self.write(''.join(_out_buffer), refresh=False) | |
|
376 | 377 | self._buffer_flush_timer.Stop() |
|
377 | 378 | |
|
378 | 379 |
General Comments 0
You need to be logged in to leave comments.
Login now