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

Python code coverage for Lib/idlelib/runscript.py

#countcontent
1n/a"""Extension to execute code outside the Python shell window.
2n/a
3n/aThis adds the following commands:
4n/a
5n/a- Check module does a full syntax check of the current module.
6n/a It also runs the tabnanny to catch any inconsistent tabs.
7n/a
8n/a- Run module executes the module's code in the __main__ namespace. The window
9n/a must have been saved previously. The module is added to sys.modules, and is
10n/a also added to the __main__ namespace.
11n/a
12n/aXXX GvR Redesign this interface (yet again) as follows:
13n/a
14n/a- Present a dialog box for ``Run Module''
15n/a
16n/a- Allow specify command line arguments in the dialog box
17n/a
18n/a"""
19n/a
20n/aimport os
21n/aimport tabnanny
22n/aimport tokenize
23n/a
24n/aimport tkinter.messagebox as tkMessageBox
25n/a
26n/afrom idlelib.config import idleConf
27n/afrom idlelib import macosx
28n/afrom idlelib import pyshell
29n/a
30n/aindent_message = """Error: Inconsistent indentation detected!
31n/a
32n/a1) Your indentation is outright incorrect (easy to fix), OR
33n/a
34n/a2) Your indentation mixes tabs and spaces.
35n/a
36n/aTo fix case 2, change all tabs to spaces by using Edit->Select All followed \
37n/aby Format->Untabify Region and specify the number of columns used by each tab.
38n/a"""
39n/a
40n/a
41n/aclass ScriptBinding:
42n/a
43n/a menudefs = [
44n/a ('run', [None,
45n/a ('Check Module', '<<check-module>>'),
46n/a ('Run Module', '<<run-module>>'), ]), ]
47n/a
48n/a def __init__(self, editwin):
49n/a self.editwin = editwin
50n/a # Provide instance variables referenced by debugger
51n/a # XXX This should be done differently
52n/a self.flist = self.editwin.flist
53n/a self.root = self.editwin.root
54n/a
55n/a if macosx.isCocoaTk():
56n/a self.editwin.text_frame.bind('<<run-module-event-2>>', self._run_module_event)
57n/a
58n/a def check_module_event(self, event):
59n/a filename = self.getfilename()
60n/a if not filename:
61n/a return 'break'
62n/a if not self.checksyntax(filename):
63n/a return 'break'
64n/a if not self.tabnanny(filename):
65n/a return 'break'
66n/a
67n/a def tabnanny(self, filename):
68n/a # XXX: tabnanny should work on binary files as well
69n/a with tokenize.open(filename) as f:
70n/a try:
71n/a tabnanny.process_tokens(tokenize.generate_tokens(f.readline))
72n/a except tokenize.TokenError as msg:
73n/a msgtxt, (lineno, start) = msg.args
74n/a self.editwin.gotoline(lineno)
75n/a self.errorbox("Tabnanny Tokenizing Error",
76n/a "Token Error: %s" % msgtxt)
77n/a return False
78n/a except tabnanny.NannyNag as nag:
79n/a # The error messages from tabnanny are too confusing...
80n/a self.editwin.gotoline(nag.get_lineno())
81n/a self.errorbox("Tab/space error", indent_message)
82n/a return False
83n/a return True
84n/a
85n/a def checksyntax(self, filename):
86n/a self.shell = shell = self.flist.open_shell()
87n/a saved_stream = shell.get_warning_stream()
88n/a shell.set_warning_stream(shell.stderr)
89n/a with open(filename, 'rb') as f:
90n/a source = f.read()
91n/a if b'\r' in source:
92n/a source = source.replace(b'\r\n', b'\n')
93n/a source = source.replace(b'\r', b'\n')
94n/a if source and source[-1] != ord(b'\n'):
95n/a source = source + b'\n'
96n/a editwin = self.editwin
97n/a text = editwin.text
98n/a text.tag_remove("ERROR", "1.0", "end")
99n/a try:
100n/a # If successful, return the compiled code
101n/a return compile(source, filename, "exec")
102n/a except (SyntaxError, OverflowError, ValueError) as value:
103n/a msg = getattr(value, 'msg', '') or value or "<no detail available>"
104n/a lineno = getattr(value, 'lineno', '') or 1
105n/a offset = getattr(value, 'offset', '') or 0
106n/a if offset == 0:
107n/a lineno += 1 #mark end of offending line
108n/a pos = "0.0 + %d lines + %d chars" % (lineno-1, offset-1)
109n/a editwin.colorize_syntax_error(text, pos)
110n/a self.errorbox("SyntaxError", "%-20s" % msg)
111n/a return False
112n/a finally:
113n/a shell.set_warning_stream(saved_stream)
114n/a
115n/a def run_module_event(self, event):
116n/a if macosx.isCocoaTk():
117n/a # Tk-Cocoa in MacOSX is broken until at least
118n/a # Tk 8.5.9, and without this rather
119n/a # crude workaround IDLE would hang when a user
120n/a # tries to run a module using the keyboard shortcut
121n/a # (the menu item works fine).
122n/a self.editwin.text_frame.after(200,
123n/a lambda: self.editwin.text_frame.event_generate('<<run-module-event-2>>'))
124n/a return 'break'
125n/a else:
126n/a return self._run_module_event(event)
127n/a
128n/a def _run_module_event(self, event):
129n/a """Run the module after setting up the environment.
130n/a
131n/a First check the syntax. If OK, make sure the shell is active and
132n/a then transfer the arguments, set the run environment's working
133n/a directory to the directory of the module being executed and also
134n/a add that directory to its sys.path if not already included.
135n/a """
136n/a
137n/a filename = self.getfilename()
138n/a if not filename:
139n/a return 'break'
140n/a code = self.checksyntax(filename)
141n/a if not code:
142n/a return 'break'
143n/a if not self.tabnanny(filename):
144n/a return 'break'
145n/a interp = self.shell.interp
146n/a if pyshell.use_subprocess:
147n/a interp.restart_subprocess(with_cwd=False, filename=
148n/a self.editwin._filename_to_unicode(filename))
149n/a dirname = os.path.dirname(filename)
150n/a # XXX Too often this discards arguments the user just set...
151n/a interp.runcommand("""if 1:
152n/a __file__ = {filename!r}
153n/a import sys as _sys
154n/a from os.path import basename as _basename
155n/a if (not _sys.argv or
156n/a _basename(_sys.argv[0]) != _basename(__file__)):
157n/a _sys.argv = [__file__]
158n/a import os as _os
159n/a _os.chdir({dirname!r})
160n/a del _sys, _basename, _os
161n/a \n""".format(filename=filename, dirname=dirname))
162n/a interp.prepend_syspath(filename)
163n/a # XXX KBK 03Jul04 When run w/o subprocess, runtime warnings still
164n/a # go to __stderr__. With subprocess, they go to the shell.
165n/a # Need to change streams in pyshell.ModifiedInterpreter.
166n/a interp.runcode(code)
167n/a return 'break'
168n/a
169n/a def getfilename(self):
170n/a """Get source filename. If not saved, offer to save (or create) file
171n/a
172n/a The debugger requires a source file. Make sure there is one, and that
173n/a the current version of the source buffer has been saved. If the user
174n/a declines to save or cancels the Save As dialog, return None.
175n/a
176n/a If the user has configured IDLE for Autosave, the file will be
177n/a silently saved if it already exists and is dirty.
178n/a
179n/a """
180n/a filename = self.editwin.io.filename
181n/a if not self.editwin.get_saved():
182n/a autosave = idleConf.GetOption('main', 'General',
183n/a 'autosave', type='bool')
184n/a if autosave and filename:
185n/a self.editwin.io.save(None)
186n/a else:
187n/a confirm = self.ask_save_dialog()
188n/a self.editwin.text.focus_set()
189n/a if confirm:
190n/a self.editwin.io.save(None)
191n/a filename = self.editwin.io.filename
192n/a else:
193n/a filename = None
194n/a return filename
195n/a
196n/a def ask_save_dialog(self):
197n/a msg = "Source Must Be Saved\n" + 5*' ' + "OK to Save?"
198n/a confirm = tkMessageBox.askokcancel(title="Save Before Run or Check",
199n/a message=msg,
200n/a default=tkMessageBox.OK,
201n/a parent=self.editwin.text)
202n/a return confirm
203n/a
204n/a def errorbox(self, title, message):
205n/a # XXX This should really be a function of EditorWindow...
206n/a tkMessageBox.showerror(title, message, parent=self.editwin.text)
207n/a self.editwin.text.focus_set()