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

Python code coverage for Lib/idlelib/ScriptBinding.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 re
22n/aimport string
23n/aimport tabnanny
24n/aimport tokenize
25n/aimport tkinter.messagebox as tkMessageBox
26n/afrom idlelib.EditorWindow import EditorWindow
27n/afrom idlelib import PyShell, IOBinding
28n/a
29n/afrom idlelib.configHandler import idleConf
30n/afrom idlelib import macosxSupport
31n/a
32n/aindent_message = """Error: Inconsistent indentation detected!
33n/a
34n/a1) Your indentation is outright incorrect (easy to fix), OR
35n/a
36n/a2) Your indentation mixes tabs and spaces.
37n/a
38n/aTo fix case 2, change all tabs to spaces by using Edit->Select All followed \
39n/aby Format->Untabify Region and specify the number of columns used by each tab.
40n/a"""
41n/a
42n/aclass ScriptBinding:
43n/a
44n/a menudefs = [
45n/a ('run', [None,
46n/a ('Check Module', '<<check-module>>'),
47n/a ('Run Module', '<<run-module>>'), ]), ]
48n/a
49n/a def __init__(self, editwin):
50n/a self.editwin = editwin
51n/a # Provide instance variables referenced by Debugger
52n/a # XXX This should be done differently
53n/a self.flist = self.editwin.flist
54n/a self.root = self.editwin.root
55n/a
56n/a if macosxSupport.runningAsOSXApp():
57n/a self.editwin.text_frame.bind('<<run-module-event-2>>', self._run_module_event)
58n/a
59n/a def check_module_event(self, event):
60n/a filename = self.getfilename()
61n/a if not filename:
62n/a return 'break'
63n/a if not self.checksyntax(filename):
64n/a return 'break'
65n/a if not self.tabnanny(filename):
66n/a return 'break'
67n/a
68n/a def tabnanny(self, filename):
69n/a # XXX: tabnanny should work on binary files as well
70n/a with tokenize.open(filename) as f:
71n/a try:
72n/a tabnanny.process_tokens(tokenize.generate_tokens(f.readline))
73n/a except tokenize.TokenError as msg:
74n/a msgtxt, (lineno, start) = msg
75n/a self.editwin.gotoline(lineno)
76n/a self.errorbox("Tabnanny Tokenizing Error",
77n/a "Token Error: %s" % msgtxt)
78n/a return False
79n/a except tabnanny.NannyNag as nag:
80n/a # The error messages from tabnanny are too confusing...
81n/a self.editwin.gotoline(nag.get_lineno())
82n/a self.errorbox("Tab/space error", indent_message)
83n/a return False
84n/a return True
85n/a
86n/a def checksyntax(self, filename):
87n/a self.shell = shell = self.flist.open_shell()
88n/a saved_stream = shell.get_warning_stream()
89n/a shell.set_warning_stream(shell.stderr)
90n/a with open(filename, 'rb') as f:
91n/a source = f.read()
92n/a if b'\r' in source:
93n/a source = source.replace(b'\r\n', b'\n')
94n/a source = source.replace(b'\r', b'\n')
95n/a if source and source[-1] != ord(b'\n'):
96n/a source = source + b'\n'
97n/a editwin = self.editwin
98n/a text = editwin.text
99n/a text.tag_remove("ERROR", "1.0", "end")
100n/a try:
101n/a # If successful, return the compiled code
102n/a return compile(source, filename, "exec")
103n/a except (SyntaxError, OverflowError, ValueError) as value:
104n/a msg = getattr(value, 'msg', '') or value or "<no detail available>"
105n/a lineno = getattr(value, 'lineno', '') or 1
106n/a offset = getattr(value, 'offset', '') or 0
107n/a if offset == 0:
108n/a lineno += 1 #mark end of offending line
109n/a pos = "0.0 + %d lines + %d chars" % (lineno-1, offset-1)
110n/a editwin.colorize_syntax_error(text, pos)
111n/a self.errorbox("SyntaxError", "%-20s" % msg)
112n/a return False
113n/a finally:
114n/a shell.set_warning_stream(saved_stream)
115n/a
116n/a def run_module_event(self, event):
117n/a if macosxSupport.runningAsOSXApp():
118n/a # Tk-Cocoa in MacOSX is broken until at least
119n/a # Tk 8.5.9, and without this rather
120n/a # crude workaround IDLE would hang when a user
121n/a # tries to run a module using the keyboard shortcut
122n/a # (the menu item works fine).
123n/a self.editwin.text_frame.after(200,
124n/a lambda: self.editwin.text_frame.event_generate('<<run-module-event-2>>'))
125n/a return 'break'
126n/a else:
127n/a return self._run_module_event(event)
128n/a
129n/a def _run_module_event(self, event):
130n/a """Run the module after setting up the environment.
131n/a
132n/a First check the syntax. If OK, make sure the shell is active and
133n/a then transfer the arguments, set the run environment's working
134n/a directory to the directory of the module being executed and also
135n/a add that directory to its sys.path if not already included.
136n/a """
137n/a
138n/a filename = self.getfilename()
139n/a if not filename:
140n/a return 'break'
141n/a code = self.checksyntax(filename)
142n/a if not code:
143n/a return 'break'
144n/a if not self.tabnanny(filename):
145n/a return 'break'
146n/a interp = self.shell.interp
147n/a if PyShell.use_subprocess:
148n/a interp.restart_subprocess(with_cwd=False)
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 master=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, master=self.editwin.text)
207n/a self.editwin.text.focus_set()