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 |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file |
@@ -194,7 +194,7 b' class ConsoleWidget(editwindow.EditWindow):' | |||||
194 | self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment']) |
|
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 | """ Write given text to buffer, while translating the ansi escape |
|
198 | """ Write given text to buffer, while translating the ansi escape | |
199 | sequences. |
|
199 | sequences. | |
200 | """ |
|
200 | """ | |
@@ -227,6 +227,7 b' class ConsoleWidget(editwindow.EditWindow):' | |||||
227 | self.SetStyling(len(text), style) |
|
227 | self.SetStyling(len(text), style) | |
228 |
|
228 | |||
229 | self.GotoPos(self.GetLength()) |
|
229 | self.GotoPos(self.GetLength()) | |
|
230 | if refresh: | |||
230 | wx.Yield() |
|
231 | wx.Yield() | |
231 |
|
232 | |||
232 |
|
233 |
@@ -21,7 +21,7 b' class IPythonXController(WxController):' | |||||
21 | # Intercept Ctrl-D to quit |
|
21 | # Intercept Ctrl-D to quit | |
22 | if event.KeyCode == ord('D') and event.ControlDown() and \ |
|
22 | if event.KeyCode == ord('D') and event.ControlDown() and \ | |
23 | self.get_current_edit_buffer()=='' and \ |
|
23 | self.get_current_edit_buffer()=='' and \ | |
24 |
|
|
24 | self._input_state == 'readline': | |
25 | wx.CallAfter(self.ask_exit) |
|
25 | wx.CallAfter(self.ask_exit) | |
26 | else: |
|
26 | else: | |
27 | WxController._on_key_down(self, event, skip=skip) |
|
27 | WxController._on_key_down(self, event, skip=skip) |
@@ -257,7 +257,7 b' class WxController(PrefilterFrontEnd, ConsoleWidget):' | |||||
257 | self._out_buffer.append(text) |
|
257 | self._out_buffer.append(text) | |
258 | self._out_buffer_lock.release() |
|
258 | self._out_buffer_lock.release() | |
259 | if not self._buffer_flush_timer.IsRunning(): |
|
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 | def show_traceback(self): |
|
263 | def show_traceback(self): | |
@@ -297,6 +297,7 b' class WxController(PrefilterFrontEnd, ConsoleWidget):' | |||||
297 | if self.debug: |
|
297 | if self.debug: | |
298 | print >>sys.__stderr__, chr(event.KeyCode) |
|
298 | print >>sys.__stderr__, chr(event.KeyCode) | |
299 | self._running_process.process.stdin.write(chr(event.KeyCode)) |
|
299 | self._running_process.process.stdin.write(chr(event.KeyCode)) | |
|
300 | self._running_process.process.stdin.flush() | |||
300 | elif event.KeyCode in (ord('('), 57): |
|
301 | elif event.KeyCode in (ord('('), 57): | |
301 | # Calltips |
|
302 | # Calltips | |
302 | event.Skip() |
|
303 | event.Skip() | |
@@ -372,7 +373,7 b' class WxController(PrefilterFrontEnd, ConsoleWidget):' | |||||
372 | _out_buffer = self._out_buffer |
|
373 | _out_buffer = self._out_buffer | |
373 | self._out_buffer = [] |
|
374 | self._out_buffer = [] | |
374 | self._out_buffer_lock.release() |
|
375 | self._out_buffer_lock.release() | |
375 | self.write(''.join(_out_buffer)) |
|
376 | self.write(''.join(_out_buffer), refresh=False) | |
376 | self._buffer_flush_timer.Stop() |
|
377 | self._buffer_flush_timer.Stop() | |
377 |
|
378 | |||
378 |
|
379 |
General Comments 0
You need to be logged in to leave comments.
Login now