emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

python-mode: Two problems with python-send-buffer


From: Slawomir Nowaczyk
Subject: python-mode: Two problems with python-send-buffer
Date: Fri, 30 Mar 2007 12:53:21 +0200

Hello,

There are two problems with how eexecfile in etc/emacs.py work.

First problem: Put the following in some buffer. Execute python-send-buffer.

    from pdb import pm
    def a():
        raise "1"
    a()

Switch to *Python*. Type pm(). Instead of starting the debugger in post
mortem mode, python will complain:

    AttributeError: 'module' object has no attribute 'last_traceback'

The reason for that is incorrect handling of exceptions in eexecfile.

Second problem: Put the following in some buffer (notice the syntax
error). Execute python-send-buffer.

   if ::

On my Windows machine, using Python 2.5, it complains:

   WindowsError: [Error 13] The process cannot access the file because it is 
being used by another process: 'c:/temp/py6036dRA'

and the temporary file remains locked until python process is exited
(or, at least, I have not found a way to unlock the file). I have tested
with Python 2.5 on Windows, maybe other versions behave differently (I
believe this is a bug in python, BTW, but we may try working around it
anyway I think).

I suggest the following patch to etc/emacs.py, which takes care of both
of those problems. The code is based on ideas from code.py and
PyShell.py from Python distributions, so I assume it is the "official"
way to do those things...

I have only tested it on Python 2.5 and 2.4 though, so it would be good
if somebody who has access to 2.3 could verify it works there too -- I
do not think we need to worry about earlier versions?

The patch isn't short, unfortunately, but I believe this is the right
way to do it.

********************************************************************************

--- EmacsCVS/etc/emacs.py       2007-03-05 12:16:55.328125000 +0100
+++ Emacs/etc/emacs.py  2007-03-05 13:57:05.875000000 +0100
@@ -25,22 +25,50 @@
 
 __all__ = ["eexecfile", "eargs", "complete", "ehelp", "eimport", "modpath"]
 
-def eexecfile (file):
-    """Execute FILE and then remove it.
-    Execute the file within the __main__ namespace.
-    If we get an exception, print a traceback with the top frame
-    (ourselves) excluded."""
+def format_exception(filename,should_remove_self):
+    type, value, tb = sys.exc_info()
+    sys.last_type = type
+    sys.last_value = value
+    sys.last_traceback = tb
+    if type is SyntaxError:
+        try: # parse the error message
+            msg, (dummy_filename, lineno, offset, line) = value
+        except:
+            pass # Not the format we expect; leave it alone
+        else:
+            # Stuff in the right filename
+            value = SyntaxError(msg, (filename, lineno, offset, line))
+            sys.last_value = value
+    res = traceback.format_exception_only(type,value)
+    if should_remove_self:    # there are some compilation errors which do not 
provide traceback so we should not massage it
+        tblist = traceback.extract_tb(tb)
+        del tblist[:1]
+        res = traceback.format_list(tblist)
+        if res:
+            res.insert(0, "Traceback (most recent call last):\n")
+        res[len(res):] = traceback.format_exception_only(type, value)
+    # traceback.print_exception(type, value, tb)
+    for line in res: print line,
+
+def eexecfile(filename):
+    "Execute an existing file --- code based on code.py and PyShell.py"
+    # We cannot use real execfile since it has a bug where the file stays 
locked forever if SyntaxError occurs
     try:
-       try: execfile (file, __main__.__dict__)
-       except:
-           (type, value, tb) = sys.exc_info ()
-           # Lose the stack frame for this location.
-           tb = tb.tb_next
-           if tb is None:      # print_exception won't do it
-               print "Traceback (most recent call last):"
-           traceback.print_exception (type, value, tb)
+        try:
+            source = open(filename, "r").read()
+            code = compile(source, filename, "exec")
+        except (OverflowError, SyntaxError, ValueError):   # Other exceptions 
(shouldn't be any...) will (correctly) fall through to "final"
+            # FIXME: When can compile() raise anything else than SyntaxError 
????
+            format_exception(filename,False)
+            return
+        try:
+            exec code in __main__.__dict__
+        except:
+            format_exception(filename,True)
     finally:
-       os.remove (file)
+       os.remove(filename)
 
 def eargs (name, imports):
     "Get arglist of NAME for Eldoc &c."

********************************************************************************

-- 
 Best wishes,
   Slawomir Nowaczyk
     ( address@hidden )

The Lords's Prayer=66 words
The Gettysburg Address=286 words
The Declaration of Independence=1322 words
U.S. Government regulations on the sale of cabbage=2691 words.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]