Commit a92bfa45 authored by Terry Jan Reedy's avatar Terry Jan Reedy

Merge with 3.3

parents 912bad7c 95a3f11f
...@@ -45,25 +45,12 @@ PORT = 0 # someday pass in host, port for remote debug capability ...@@ -45,25 +45,12 @@ PORT = 0 # someday pass in host, port for remote debug capability
# internal warnings to the console. ScriptBinding.check_syntax() will # internal warnings to the console. ScriptBinding.check_syntax() will
# temporarily redirect the stream to the shell window to display warnings when # temporarily redirect the stream to the shell window to display warnings when
# checking user's code. # checking user's code.
global warning_stream warning_stream = sys.__stderr__ # None, at least on Windows, if no console.
warning_stream = sys.__stderr__ import warnings
try:
import warnings def idle_formatwarning(message, category, filename, lineno, line=None):
except ImportError: """Format warnings the IDLE way."""
pass
else:
def idle_showwarning(message, category, filename, lineno,
file=None, line=None):
if file is None:
file = warning_stream
try:
file.write(warnings.formatwarning(message, category, filename,
lineno, line=line))
except OSError:
pass ## file (probably __stderr__) is invalid, warning dropped.
warnings.showwarning = idle_showwarning
def idle_formatwarning(message, category, filename, lineno, line=None):
"""Format warnings the IDLE way"""
s = "\nWarning (from warnings module):\n" s = "\nWarning (from warnings module):\n"
s += ' File \"%s\", line %s\n' % (filename, lineno) s += ' File \"%s\", line %s\n' % (filename, lineno)
if line is None: if line is None:
...@@ -71,9 +58,42 @@ else: ...@@ -71,9 +58,42 @@ else:
line = line.strip() line = line.strip()
if line: if line:
s += " %s\n" % line s += " %s\n" % line
s += "%s: %s\n>>> " % (category.__name__, message) s += "%s: %s\n" % (category.__name__, message)
return s return s
warnings.formatwarning = idle_formatwarning
def idle_showwarning(
message, category, filename, lineno, file=None, line=None):
"""Show Idle-format warning (after replacing warnings.showwarning).
The differences are the formatter called, the file=None replacement,
which can be None, the capture of the consequence AttributeError,
and the output of a hard-coded prompt.
"""
if file is None:
file = warning_stream
try:
file.write(idle_formatwarning(
message, category, filename, lineno, line=line))
file.write(">>> ")
except (AttributeError, OSError):
pass # if file (probably __stderr__) is invalid, skip warning.
_warnings_showwarning = None
def capture_warnings(capture):
"Replace warning.showwarning with idle_showwarning, or reverse."
global _warnings_showwarning
if capture:
if _warnings_showwarning is None:
_warnings_showwarning = warnings.showwarning
warnings.showwarning = idle_showwarning
else:
if _warnings_showwarning is not None:
warnings.showwarning = _warnings_showwarning
_warnings_showwarning = None
capture_warnings(True)
def extended_linecache_checkcache(filename=None, def extended_linecache_checkcache(filename=None,
orig_checkcache=linecache.checkcache): orig_checkcache=linecache.checkcache):
...@@ -1425,6 +1445,7 @@ echo "import sys; print(sys.argv)" | idle - "foobar" ...@@ -1425,6 +1445,7 @@ echo "import sys; print(sys.argv)" | idle - "foobar"
def main(): def main():
global flist, root, use_subprocess global flist, root, use_subprocess
capture_warnings(True)
use_subprocess = True use_subprocess = True
enable_shell = False enable_shell = False
enable_edit = False enable_edit = False
...@@ -1559,7 +1580,10 @@ def main(): ...@@ -1559,7 +1580,10 @@ def main():
while flist.inversedict: # keep IDLE running while files are open. while flist.inversedict: # keep IDLE running while files are open.
root.mainloop() root.mainloop()
root.destroy() root.destroy()
capture_warnings(False)
if __name__ == "__main__": if __name__ == "__main__":
sys.modules['PyShell'] = sys.modules['__main__'] sys.modules['PyShell'] = sys.modules['__main__']
main() main()
capture_warnings(False) # Make sure turned off; see issue 18081
'''Test warnings replacement in PyShell.py and run.py.
This file could be expanded to include traceback overrides
(in same two modules). If so, change name.
Revise if output destination changes (http://bugs.python.org/issue18318).
Make sure warnings module is left unaltered (http://bugs.python.org/issue18081).
'''
import unittest
from test.support import captured_stderr
import warnings
# Try to capture default showwarning before Idle modules are imported.
showwarning = warnings.showwarning
# But if we run this file within idle, we are in the middle of the run.main loop
# and default showwarnings has already been replaced.
running_in_idle = 'idle' in showwarning.__name__
from idlelib import run
from idlelib import PyShell as shell
# The following was generated from PyShell.idle_formatwarning
# and checked as matching expectation.
idlemsg = '''
Warning (from warnings module):
File "test_warning.py", line 99
Line of code
UserWarning: Test
'''
shellmsg = idlemsg + ">>> "
class RunWarnTest(unittest.TestCase):
@unittest.skipIf(running_in_idle, "Does not work when run within Idle.")
def test_showwarnings(self):
self.assertIs(warnings.showwarning, showwarning)
run.capture_warnings(True)
self.assertIs(warnings.showwarning, run.idle_showwarning_subproc)
run.capture_warnings(False)
self.assertIs(warnings.showwarning, showwarning)
def test_run_show(self):
with captured_stderr() as f:
run.idle_showwarning_subproc(
'Test', UserWarning, 'test_warning.py', 99, f, 'Line of code')
# The following uses .splitlines to erase line-ending differences
self.assertEqual(idlemsg.splitlines(), f.getvalue().splitlines())
class ShellWarnTest(unittest.TestCase):
@unittest.skipIf(running_in_idle, "Does not work when run within Idle.")
def test_showwarnings(self):
self.assertIs(warnings.showwarning, showwarning)
shell.capture_warnings(True)
self.assertIs(warnings.showwarning, shell.idle_showwarning)
shell.capture_warnings(False)
self.assertIs(warnings.showwarning, showwarning)
def test_idle_formatter(self):
# Will fail if format changed without regenerating idlemsg
s = shell.idle_formatwarning(
'Test', UserWarning, 'test_warning.py', 99, 'Line of code')
self.assertEqual(idlemsg, s)
def test_shell_show(self):
with captured_stderr() as f:
shell.idle_showwarning(
'Test', UserWarning, 'test_warning.py', 99, f, 'Line of code')
self.assertEqual(shellmsg.splitlines(), f.getvalue().splitlines())
if __name__ == '__main__':
unittest.main(verbosity=2, exit=False)
...@@ -23,28 +23,39 @@ import __main__ ...@@ -23,28 +23,39 @@ import __main__
LOCALHOST = '127.0.0.1' LOCALHOST = '127.0.0.1'
try: import warnings
import warnings
except ImportError:
pass
else:
def idle_formatwarning_subproc(message, category, filename, lineno,
line=None):
"""Format warnings the IDLE way"""
s = "\nWarning (from warnings module):\n"
s += ' File \"%s\", line %s\n' % (filename, lineno)
if line is None:
line = linecache.getline(filename, lineno)
line = line.strip()
if line:
s += " %s\n" % line
s += "%s: %s\n" % (category.__name__, message)
return s
warnings.formatwarning = idle_formatwarning_subproc
def idle_showwarning_subproc(
message, category, filename, lineno, file=None, line=None):
"""Show Idle-format warning after replacing warnings.showwarning.
tcl = tkinter.Tcl() The only difference is the formatter called.
"""
if file is None:
file = sys.stderr
try:
file.write(PyShell.idle_formatwarning(
message, category, filename, lineno, line))
except IOError:
pass # the file (probably stderr) is invalid - this warning gets lost.
_warnings_showwarning = None
def capture_warnings(capture):
"Replace warning.showwarning with idle_showwarning_subproc, or reverse."
global _warnings_showwarning
if capture:
if _warnings_showwarning is None:
_warnings_showwarning = warnings.showwarning
warnings.showwarning = idle_showwarning_subproc
else:
if _warnings_showwarning is not None:
warnings.showwarning = _warnings_showwarning
_warnings_showwarning = None
capture_warnings(True)
tcl = tkinter.Tcl()
def handle_tk_events(tcl=tcl): def handle_tk_events(tcl=tcl):
"""Process any tk events that are ready to be dispatched if tkinter """Process any tk events that are ready to be dispatched if tkinter
...@@ -52,7 +63,6 @@ def handle_tk_events(tcl=tcl): ...@@ -52,7 +63,6 @@ def handle_tk_events(tcl=tcl):
loaded.""" loaded."""
tcl.eval("update") tcl.eval("update")
# Thread shared globals: Establish a queue between a subthread (which handles # Thread shared globals: Establish a queue between a subthread (which handles
# the socket) and the main thread (which runs user code), plus global # the socket) and the main thread (which runs user code), plus global
# completion, exit and interruptable (the main thread) flags: # completion, exit and interruptable (the main thread) flags:
...@@ -91,6 +101,8 @@ def main(del_exitfunc=False): ...@@ -91,6 +101,8 @@ def main(del_exitfunc=False):
print("IDLE Subprocess: no IP port passed in sys.argv.", print("IDLE Subprocess: no IP port passed in sys.argv.",
file=sys.__stderr__) file=sys.__stderr__)
return return
capture_warnings(True)
sys.argv[:] = [""] sys.argv[:] = [""]
sockthread = threading.Thread(target=manage_socket, sockthread = threading.Thread(target=manage_socket,
name='SockThread', name='SockThread',
...@@ -118,6 +130,7 @@ def main(del_exitfunc=False): ...@@ -118,6 +130,7 @@ def main(del_exitfunc=False):
exit_now = True exit_now = True
continue continue
except SystemExit: except SystemExit:
capture_warnings(False)
raise raise
except: except:
type, value, tb = sys.exc_info() type, value, tb = sys.exc_info()
...@@ -247,6 +260,7 @@ def exit(): ...@@ -247,6 +260,7 @@ def exit():
if no_exitfunc: if no_exitfunc:
import atexit import atexit
atexit._clear() atexit._clear()
capture_warnings(False)
sys.exit(0) sys.exit(0)
class MyRPCServer(rpc.RPCServer): class MyRPCServer(rpc.RPCServer):
...@@ -386,3 +400,5 @@ class Executive(object): ...@@ -386,3 +400,5 @@ class Executive(object):
sys.last_value = val sys.last_value = val
item = StackViewer.StackTreeItem(flist, tb) item = StackViewer.StackTreeItem(flist, tb)
return RemoteObjectBrowser.remote_object_tree_item(item) return RemoteObjectBrowser.remote_object_tree_item(item)
capture_warnings(False) # Make sure turned off; see issue 18081
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment