3
votes

There appears to be a pretty significant bug in C-M-x, a.k.a. python-shell-send-defun in the builtin python mode

  1. start emacs
  2. create a new file, let's call it test.py
  3. C-c C-p to run-python
  4. in the test.py buffer, type some simple function, like

    def f(x):
        return x+1
    
  5. C-M-x for python-shell-send-defun

we get:

    return x+1
SyntaxError: 'return' outside function

So what's happening here is that python-shell-send-defun is only sending one line, not both lines as we would expect it to (the corresponding command in emacs lisp major mode for instance works correctly in sending the entire multiline defun prior to the cursor). What's going on here? I tested this in both emacs 25 gui version in Mac OS as well as emacs 24 in Ubuntu. Both exhibit the same error.

Is this a bug, or am I misunderstanding what python-shell-send-defun actually does?

Update: with some further testing, it appears that this error only occurs for functions that start on the very first line. If we insert a blank line right above def f(x):, C-M-x works perfectly.

1

1 Answers

0
votes

Yes, this looks like a bug and should be reported as one. That function should probably be rewritten to have a check as follows

(defun python-shell-send-defun (&optional arg msg)
  "Send the current defun to inferior Python process.
When argument ARG is non-nil do not include decorators.  When
optional argument MSG is non-nil, forces display of a
user-friendly message if there's no process running; defaults to
t when called interactively."
  (interactive (list current-prefix-arg t))
  (save-excursion
    (python-shell-send-region
     (progn
       (end-of-line 1)
       (while (and (or (python-nav-beginning-of-defun)
                       (beginning-of-line 1))
                   (> (current-indentation) 0)))
       (when (not arg)
         (while (and (forward-line -1)
                     (looking-at (python-rx decorator))))
         ;; add a check here to see if we are on the first line
         (and (not (bobp)) (forward-line 1)))
       (point-marker))
     (progn
       (or (python-nav-end-of-defun)
           (end-of-line 1))
       (point-marker))
     nil  ;; noop
     msg)))