ยปCore Development>Code coverage>Lib/idlelib/run.py

Python code coverage for Lib/idlelib/run.py

#countcontent
1n/aimport io
2n/aimport linecache
3n/aimport queue
4n/aimport sys
5n/aimport time
6n/aimport traceback
7n/aimport _thread as thread
8n/aimport threading
9n/aimport warnings
10n/a
11n/aimport tkinter # Tcl, deletions, messagebox if startup fails
12n/a
13n/afrom idlelib import autocomplete # AutoComplete, fetch_encodings
14n/afrom idlelib import calltips # CallTips
15n/afrom idlelib import debugger_r # start_debugger
16n/afrom idlelib import debugobj_r # remote_object_tree_item
17n/afrom idlelib import iomenu # encoding
18n/afrom idlelib import rpc # multiple objects
19n/afrom idlelib import stackviewer # StackTreeItem
20n/aimport __main__
21n/a
22n/afor mod in ('simpledialog', 'messagebox', 'font',
23n/a 'dialog', 'filedialog', 'commondialog',
24n/a 'ttk'):
25n/a delattr(tkinter, mod)
26n/a del sys.modules['tkinter.' + mod]
27n/a
28n/aLOCALHOST = '127.0.0.1'
29n/a
30n/a
31n/adef idle_formatwarning(message, category, filename, lineno, line=None):
32n/a """Format warnings the IDLE way."""
33n/a
34n/a s = "\nWarning (from warnings module):\n"
35n/a s += ' File \"%s\", line %s\n' % (filename, lineno)
36n/a if line is None:
37n/a line = linecache.getline(filename, lineno)
38n/a line = line.strip()
39n/a if line:
40n/a s += " %s\n" % line
41n/a s += "%s: %s\n" % (category.__name__, message)
42n/a return s
43n/a
44n/adef idle_showwarning_subproc(
45n/a message, category, filename, lineno, file=None, line=None):
46n/a """Show Idle-format warning after replacing warnings.showwarning.
47n/a
48n/a The only difference is the formatter called.
49n/a """
50n/a if file is None:
51n/a file = sys.stderr
52n/a try:
53n/a file.write(idle_formatwarning(
54n/a message, category, filename, lineno, line))
55n/a except IOError:
56n/a pass # the file (probably stderr) is invalid - this warning gets lost.
57n/a
58n/a_warnings_showwarning = None
59n/a
60n/adef capture_warnings(capture):
61n/a "Replace warning.showwarning with idle_showwarning_subproc, or reverse."
62n/a
63n/a global _warnings_showwarning
64n/a if capture:
65n/a if _warnings_showwarning is None:
66n/a _warnings_showwarning = warnings.showwarning
67n/a warnings.showwarning = idle_showwarning_subproc
68n/a else:
69n/a if _warnings_showwarning is not None:
70n/a warnings.showwarning = _warnings_showwarning
71n/a _warnings_showwarning = None
72n/a
73n/acapture_warnings(True)
74n/atcl = tkinter.Tcl()
75n/a
76n/adef handle_tk_events(tcl=tcl):
77n/a """Process any tk events that are ready to be dispatched if tkinter
78n/a has been imported, a tcl interpreter has been created and tk has been
79n/a loaded."""
80n/a tcl.eval("update")
81n/a
82n/a# Thread shared globals: Establish a queue between a subthread (which handles
83n/a# the socket) and the main thread (which runs user code), plus global
84n/a# completion, exit and interruptable (the main thread) flags:
85n/a
86n/aexit_now = False
87n/aquitting = False
88n/ainterruptable = False
89n/a
90n/adef main(del_exitfunc=False):
91n/a """Start the Python execution server in a subprocess
92n/a
93n/a In the Python subprocess, RPCServer is instantiated with handlerclass
94n/a MyHandler, which inherits register/unregister methods from RPCHandler via
95n/a the mix-in class SocketIO.
96n/a
97n/a When the RPCServer 'server' is instantiated, the TCPServer initialization
98n/a creates an instance of run.MyHandler and calls its handle() method.
99n/a handle() instantiates a run.Executive object, passing it a reference to the
100n/a MyHandler object. That reference is saved as attribute rpchandler of the
101n/a Executive instance. The Executive methods have access to the reference and
102n/a can pass it on to entities that they command
103n/a (e.g. debugger_r.Debugger.start_debugger()). The latter, in turn, can
104n/a call MyHandler(SocketIO) register/unregister methods via the reference to
105n/a register and unregister themselves.
106n/a
107n/a """
108n/a global exit_now
109n/a global quitting
110n/a global no_exitfunc
111n/a no_exitfunc = del_exitfunc
112n/a #time.sleep(15) # test subprocess not responding
113n/a try:
114n/a assert(len(sys.argv) > 1)
115n/a port = int(sys.argv[-1])
116n/a except:
117n/a print("IDLE Subprocess: no IP port passed in sys.argv.",
118n/a file=sys.__stderr__)
119n/a return
120n/a
121n/a capture_warnings(True)
122n/a sys.argv[:] = [""]
123n/a sockthread = threading.Thread(target=manage_socket,
124n/a name='SockThread',
125n/a args=((LOCALHOST, port),))
126n/a sockthread.daemon = True
127n/a sockthread.start()
128n/a while 1:
129n/a try:
130n/a if exit_now:
131n/a try:
132n/a exit()
133n/a except KeyboardInterrupt:
134n/a # exiting but got an extra KBI? Try again!
135n/a continue
136n/a try:
137n/a seq, request = rpc.request_queue.get(block=True, timeout=0.05)
138n/a except queue.Empty:
139n/a handle_tk_events()
140n/a continue
141n/a method, args, kwargs = request
142n/a ret = method(*args, **kwargs)
143n/a rpc.response_queue.put((seq, ret))
144n/a except KeyboardInterrupt:
145n/a if quitting:
146n/a exit_now = True
147n/a continue
148n/a except SystemExit:
149n/a capture_warnings(False)
150n/a raise
151n/a except:
152n/a type, value, tb = sys.exc_info()
153n/a try:
154n/a print_exception()
155n/a rpc.response_queue.put((seq, None))
156n/a except:
157n/a # Link didn't work, print same exception to __stderr__
158n/a traceback.print_exception(type, value, tb, file=sys.__stderr__)
159n/a exit()
160n/a else:
161n/a continue
162n/a
163n/adef manage_socket(address):
164n/a for i in range(3):
165n/a time.sleep(i)
166n/a try:
167n/a server = MyRPCServer(address, MyHandler)
168n/a break
169n/a except OSError as err:
170n/a print("IDLE Subprocess: OSError: " + err.args[1] +
171n/a ", retrying....", file=sys.__stderr__)
172n/a socket_error = err
173n/a else:
174n/a print("IDLE Subprocess: Connection to "
175n/a "IDLE GUI failed, exiting.", file=sys.__stderr__)
176n/a show_socket_error(socket_error, address)
177n/a global exit_now
178n/a exit_now = True
179n/a return
180n/a server.handle_request() # A single request only
181n/a
182n/adef show_socket_error(err, address):
183n/a import tkinter
184n/a import tkinter.messagebox as tkMessageBox
185n/a root = tkinter.Tk()
186n/a root.withdraw()
187n/a if err.args[0] == 61: # connection refused
188n/a msg = "IDLE's subprocess can't connect to %s:%d. This may be due "\
189n/a "to your personal firewall configuration. It is safe to "\
190n/a "allow this internal connection because no data is visible on "\
191n/a "external ports." % address
192n/a tkMessageBox.showerror("IDLE Subprocess Error", msg, parent=root)
193n/a else:
194n/a tkMessageBox.showerror("IDLE Subprocess Error",
195n/a "Socket Error: %s" % err.args[1], parent=root)
196n/a root.destroy()
197n/a
198n/adef print_exception():
199n/a import linecache
200n/a linecache.checkcache()
201n/a flush_stdout()
202n/a efile = sys.stderr
203n/a typ, val, tb = excinfo = sys.exc_info()
204n/a sys.last_type, sys.last_value, sys.last_traceback = excinfo
205n/a seen = set()
206n/a
207n/a def print_exc(typ, exc, tb):
208n/a seen.add(exc)
209n/a context = exc.__context__
210n/a cause = exc.__cause__
211n/a if cause is not None and cause not in seen:
212n/a print_exc(type(cause), cause, cause.__traceback__)
213n/a print("\nThe above exception was the direct cause "
214n/a "of the following exception:\n", file=efile)
215n/a elif (context is not None and
216n/a not exc.__suppress_context__ and
217n/a context not in seen):
218n/a print_exc(type(context), context, context.__traceback__)
219n/a print("\nDuring handling of the above exception, "
220n/a "another exception occurred:\n", file=efile)
221n/a if tb:
222n/a tbe = traceback.extract_tb(tb)
223n/a print('Traceback (most recent call last):', file=efile)
224n/a exclude = ("run.py", "rpc.py", "threading.py", "queue.py",
225n/a "debugger_r.py", "bdb.py")
226n/a cleanup_traceback(tbe, exclude)
227n/a traceback.print_list(tbe, file=efile)
228n/a lines = traceback.format_exception_only(typ, exc)
229n/a for line in lines:
230n/a print(line, end='', file=efile)
231n/a
232n/a print_exc(typ, val, tb)
233n/a
234n/adef cleanup_traceback(tb, exclude):
235n/a "Remove excluded traces from beginning/end of tb; get cached lines"
236n/a orig_tb = tb[:]
237n/a while tb:
238n/a for rpcfile in exclude:
239n/a if tb[0][0].count(rpcfile):
240n/a break # found an exclude, break for: and delete tb[0]
241n/a else:
242n/a break # no excludes, have left RPC code, break while:
243n/a del tb[0]
244n/a while tb:
245n/a for rpcfile in exclude:
246n/a if tb[-1][0].count(rpcfile):
247n/a break
248n/a else:
249n/a break
250n/a del tb[-1]
251n/a if len(tb) == 0:
252n/a # exception was in IDLE internals, don't prune!
253n/a tb[:] = orig_tb[:]
254n/a print("** IDLE Internal Exception: ", file=sys.stderr)
255n/a rpchandler = rpc.objecttable['exec'].rpchandler
256n/a for i in range(len(tb)):
257n/a fn, ln, nm, line = tb[i]
258n/a if nm == '?':
259n/a nm = "-toplevel-"
260n/a if not line and fn.startswith("<pyshell#"):
261n/a line = rpchandler.remotecall('linecache', 'getline',
262n/a (fn, ln), {})
263n/a tb[i] = fn, ln, nm, line
264n/a
265n/adef flush_stdout():
266n/a """XXX How to do this now?"""
267n/a
268n/adef exit():
269n/a """Exit subprocess, possibly after first clearing exit functions.
270n/a
271n/a If config-main.cfg/.def 'General' 'delete-exitfunc' is True, then any
272n/a functions registered with atexit will be removed before exiting.
273n/a (VPython support)
274n/a
275n/a """
276n/a if no_exitfunc:
277n/a import atexit
278n/a atexit._clear()
279n/a capture_warnings(False)
280n/a sys.exit(0)
281n/a
282n/a
283n/aclass MyRPCServer(rpc.RPCServer):
284n/a
285n/a def handle_error(self, request, client_address):
286n/a """Override RPCServer method for IDLE
287n/a
288n/a Interrupt the MainThread and exit server if link is dropped.
289n/a
290n/a """
291n/a global quitting
292n/a try:
293n/a raise
294n/a except SystemExit:
295n/a raise
296n/a except EOFError:
297n/a global exit_now
298n/a exit_now = True
299n/a thread.interrupt_main()
300n/a except:
301n/a erf = sys.__stderr__
302n/a print('\n' + '-'*40, file=erf)
303n/a print('Unhandled server exception!', file=erf)
304n/a print('Thread: %s' % threading.current_thread().name, file=erf)
305n/a print('Client Address: ', client_address, file=erf)
306n/a print('Request: ', repr(request), file=erf)
307n/a traceback.print_exc(file=erf)
308n/a print('\n*** Unrecoverable, server exiting!', file=erf)
309n/a print('-'*40, file=erf)
310n/a quitting = True
311n/a thread.interrupt_main()
312n/a
313n/a
314n/a# Pseudofiles for shell-remote communication (also used in pyshell)
315n/a
316n/aclass PseudoFile(io.TextIOBase):
317n/a
318n/a def __init__(self, shell, tags, encoding=None):
319n/a self.shell = shell
320n/a self.tags = tags
321n/a self._encoding = encoding
322n/a
323n/a @property
324n/a def encoding(self):
325n/a return self._encoding
326n/a
327n/a @property
328n/a def name(self):
329n/a return '<%s>' % self.tags
330n/a
331n/a def isatty(self):
332n/a return True
333n/a
334n/a
335n/aclass PseudoOutputFile(PseudoFile):
336n/a
337n/a def writable(self):
338n/a return True
339n/a
340n/a def write(self, s):
341n/a if self.closed:
342n/a raise ValueError("write to closed file")
343n/a if type(s) is not str:
344n/a if not isinstance(s, str):
345n/a raise TypeError('must be str, not ' + type(s).__name__)
346n/a # See issue #19481
347n/a s = str.__str__(s)
348n/a return self.shell.write(s, self.tags)
349n/a
350n/a
351n/aclass PseudoInputFile(PseudoFile):
352n/a
353n/a def __init__(self, shell, tags, encoding=None):
354n/a PseudoFile.__init__(self, shell, tags, encoding)
355n/a self._line_buffer = ''
356n/a
357n/a def readable(self):
358n/a return True
359n/a
360n/a def read(self, size=-1):
361n/a if self.closed:
362n/a raise ValueError("read from closed file")
363n/a if size is None:
364n/a size = -1
365n/a elif not isinstance(size, int):
366n/a raise TypeError('must be int, not ' + type(size).__name__)
367n/a result = self._line_buffer
368n/a self._line_buffer = ''
369n/a if size < 0:
370n/a while True:
371n/a line = self.shell.readline()
372n/a if not line: break
373n/a result += line
374n/a else:
375n/a while len(result) < size:
376n/a line = self.shell.readline()
377n/a if not line: break
378n/a result += line
379n/a self._line_buffer = result[size:]
380n/a result = result[:size]
381n/a return result
382n/a
383n/a def readline(self, size=-1):
384n/a if self.closed:
385n/a raise ValueError("read from closed file")
386n/a if size is None:
387n/a size = -1
388n/a elif not isinstance(size, int):
389n/a raise TypeError('must be int, not ' + type(size).__name__)
390n/a line = self._line_buffer or self.shell.readline()
391n/a if size < 0:
392n/a size = len(line)
393n/a eol = line.find('\n', 0, size)
394n/a if eol >= 0:
395n/a size = eol + 1
396n/a self._line_buffer = line[size:]
397n/a return line[:size]
398n/a
399n/a def close(self):
400n/a self.shell.close()
401n/a
402n/a
403n/aclass MyHandler(rpc.RPCHandler):
404n/a
405n/a def handle(self):
406n/a """Override base method"""
407n/a executive = Executive(self)
408n/a self.register("exec", executive)
409n/a self.console = self.get_remote_proxy("console")
410n/a sys.stdin = PseudoInputFile(self.console, "stdin",
411n/a iomenu.encoding)
412n/a sys.stdout = PseudoOutputFile(self.console, "stdout",
413n/a iomenu.encoding)
414n/a sys.stderr = PseudoOutputFile(self.console, "stderr",
415n/a iomenu.encoding)
416n/a
417n/a sys.displayhook = rpc.displayhook
418n/a # page help() text to shell.
419n/a import pydoc # import must be done here to capture i/o binding
420n/a pydoc.pager = pydoc.plainpager
421n/a
422n/a # Keep a reference to stdin so that it won't try to exit IDLE if
423n/a # sys.stdin gets changed from within IDLE's shell. See issue17838.
424n/a self._keep_stdin = sys.stdin
425n/a
426n/a self.interp = self.get_remote_proxy("interp")
427n/a rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
428n/a
429n/a def exithook(self):
430n/a "override SocketIO method - wait for MainThread to shut us down"
431n/a time.sleep(10)
432n/a
433n/a def EOFhook(self):
434n/a "Override SocketIO method - terminate wait on callback and exit thread"
435n/a global quitting
436n/a quitting = True
437n/a thread.interrupt_main()
438n/a
439n/a def decode_interrupthook(self):
440n/a "interrupt awakened thread"
441n/a global quitting
442n/a quitting = True
443n/a thread.interrupt_main()
444n/a
445n/a
446n/aclass Executive(object):
447n/a
448n/a def __init__(self, rpchandler):
449n/a self.rpchandler = rpchandler
450n/a self.locals = __main__.__dict__
451n/a self.calltip = calltips.CallTips()
452n/a self.autocomplete = autocomplete.AutoComplete()
453n/a
454n/a def runcode(self, code):
455n/a global interruptable
456n/a try:
457n/a self.usr_exc_info = None
458n/a interruptable = True
459n/a try:
460n/a exec(code, self.locals)
461n/a finally:
462n/a interruptable = False
463n/a except SystemExit:
464n/a # Scripts that raise SystemExit should just
465n/a # return to the interactive prompt
466n/a pass
467n/a except:
468n/a self.usr_exc_info = sys.exc_info()
469n/a if quitting:
470n/a exit()
471n/a # even print a user code SystemExit exception, continue
472n/a print_exception()
473n/a jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
474n/a if jit:
475n/a self.rpchandler.interp.open_remote_stack_viewer()
476n/a else:
477n/a flush_stdout()
478n/a
479n/a def interrupt_the_server(self):
480n/a if interruptable:
481n/a thread.interrupt_main()
482n/a
483n/a def start_the_debugger(self, gui_adap_oid):
484n/a return debugger_r.start_debugger(self.rpchandler, gui_adap_oid)
485n/a
486n/a def stop_the_debugger(self, idb_adap_oid):
487n/a "Unregister the Idb Adapter. Link objects and Idb then subject to GC"
488n/a self.rpchandler.unregister(idb_adap_oid)
489n/a
490n/a def get_the_calltip(self, name):
491n/a return self.calltip.fetch_tip(name)
492n/a
493n/a def get_the_completion_list(self, what, mode):
494n/a return self.autocomplete.fetch_completions(what, mode)
495n/a
496n/a def stackviewer(self, flist_oid=None):
497n/a if self.usr_exc_info:
498n/a typ, val, tb = self.usr_exc_info
499n/a else:
500n/a return None
501n/a flist = None
502n/a if flist_oid is not None:
503n/a flist = self.rpchandler.get_remote_proxy(flist_oid)
504n/a while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
505n/a tb = tb.tb_next
506n/a sys.last_type = typ
507n/a sys.last_value = val
508n/a item = stackviewer.StackTreeItem(flist, tb)
509n/a return debugobj_r.remote_object_tree_item(item)
510n/a
511n/acapture_warnings(False) # Make sure turned off; see issue 18081