diff options
author | Kurt B. Kaiser <kbk@shore.net> | 2003-01-31 05:06:43 (GMT) |
---|---|---|
committer | Kurt B. Kaiser <kbk@shore.net> | 2003-01-31 05:06:43 (GMT) |
commit | 8cd0def10dc028e3522a04bd136c67f92f90da04 (patch) | |
tree | 29e3d148f95ddc1c3c824f6d7c32ed61ca4364ec /Lib/idlelib/rpc.py | |
parent | d17406830cef6ee1f34e42013ae60e69dc91d71f (diff) | |
download | cpython-8cd0def10dc028e3522a04bd136c67f92f90da04.zip cpython-8cd0def10dc028e3522a04bd136c67f92f90da04.tar.gz cpython-8cd0def10dc028e3522a04bd136c67f92f90da04.tar.bz2 |
M PyShell.py
M rpc.py
SF Bug 676398 Doesn't handle non-built-in exceptions
1. Move exception formatting to the subprocess; allows subclassing of
exceptions, including subclasses created in the shell without
introducing excessive complexity in the RPC mechanism.
2. Provide access to linecache from subprocess to support this.
Diffstat (limited to 'Lib/idlelib/rpc.py')
-rw-r--r-- | Lib/idlelib/rpc.py | 78 |
1 files changed, 41 insertions, 37 deletions
diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py index c7644e1..b50643a 100644 --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -154,26 +154,49 @@ class SocketIO: ret = remoteref(ret) return ("OK", ret) except: - ##traceback.print_exc(file=sys.__stderr__) + self.debug("localcall:EXCEPTION") + efile = sys.stderr typ, val, tb = info = sys.exc_info() sys.last_type, sys.last_value, sys.last_traceback = info - if isinstance(typ, type(Exception)): - # Class exception - mod = typ.__module__ - name = typ.__name__ - if issubclass(typ, Exception): - args = val.args - else: - args = (str(val),) + tbe = traceback.extract_tb(tb) + print >>efile, 'Traceback (most recent call last):' + exclude = ("run.py", "rpc.py", "RemoteDebugger.py", "bdb.py") + self.cleanup_traceback(tbe, exclude) + traceback.print_list(tbe, file=efile) + lines = traceback.format_exception_only(typ, val) + for line in lines: + print>>efile, line, + return ("EXCEPTION", None) + + def cleanup_traceback(self, tb, exclude): + "Remove excluded traces from beginning/end of tb; get cached lines" + orig_tb = tb[:] + while tb: + for rpcfile in exclude: + if tb[0][0].count(rpcfile): + break # found an exclude, break for: and delete tb[0] else: - # User string exception - mod = None - name = typ - if val is None: val = '' - args = str(val) - tb = traceback.extract_tb(tb) - self.debug("localcall:EXCEPTION: ", mod, name, args, tb) - return ("EXCEPTION", (mod, name, args, tb)) + break # no excludes, have left RPC code, break while: + del tb[0] + while tb: + for rpcfile in exclude: + if tb[-1][0].count(rpcfile): + break + else: + break + del tb[-1] + if len(tb) == 0: + # error was in RPC internals, don't prune! + tb[:] = orig_tb[:] + print>>sys.stderr, "** RPC Internal Error: ", tb + for i in range(len(tb)): + fn, ln, nm, line = tb[i] + if nm == '?': + nm = "-toplevel-" + if not line and fn.startswith("<pyshell#"): + line = self.remotecall('linecache', 'getline', + (fn, ln), {}) + tb[i] = fn, ln, nm, line def remotecall(self, oid, methodname, args, kwargs): self.debug("calling asynccall via remotecall") @@ -198,26 +221,7 @@ class SocketIO: if how == "OK": return what if how == "EXCEPTION": - self.debug("decoderesponse: EXCEPTION:", what) - mod, name, args, tb = what - self.traceback = tb - if mod: # not string exception - try: - __import__(mod) - module = sys.modules[mod] - except ImportError: - pass - else: - try: - cls = getattr(module, name) - except AttributeError: - pass - else: - # instantiate a built-in exception object and raise it - raise getattr(__import__(mod), name)(*args) - name = mod + "." + name - # do the best we can: - raise name, args + raise Exception, "RPC SocketIO.decoderesponse exception" if how == "ERROR": self.debug("decoderesponse: Internal ERROR:", what) raise RuntimeError, what |