Completion hangs in python script buffer

Bug #980049 reported by Richard Stanton
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
python-mode.el
Fix Released
Medium
Andreas Roehler

Bug Description

Under r934, if I open a python script, press C-c C-c to run it (to get around another bug), then type some characters and press ESC-TAB in the script buffer to try to complete the text, Emacs hangs (though it can eventually be rescued with C-g).

If I set debug-on-quit to t, here's what I see when I press C-g:

Debugger entered--Lisp error: (quit)
  accept-process-output(#<process /Library/Frameworks/EPD64.framework/Versions/7.2/bin/ipython> 1)
  (while (not comint-redirect-completed) (accept-process-output proc 1))
  (save-current-buffer (set-buffer procbuf) (interrupt-process proc comint-ptyp) (while (not comint-redirect-completed) (accept-process-output proc 1)))
  (with-current-buffer procbuf (interrupt-process proc comint-ptyp) (while (not comint-redirect-completed) (accept-process-output proc 1)))
  (condition-case nil (progn (if lines (with-current-buffer procbuf (py-shell-redirect-send-command-to-process "" outbuf proc nil t) (while (not comint-redirect-completed) (accept-process-output proc 1)))) (with-current-buffer outbuf (delete-region (point-min) (point-max))) (with-current-buffer procbuf (py-shell-redirect-send-command-to-process cmd outbuf proc nil t) (while (not comint-redirect-completed) (accept-process-output proc 1))) (with-current-buffer outbuf (buffer-substring (point-min) (point-max)))) (quit (with-current-buffer procbuf (interrupt-process proc comint-ptyp) (while (not comint-redirect-completed) (accept-process-output proc 1))) (signal (quote quit) nil)))
  (unwind-protect (condition-case nil (progn (if lines (with-current-buffer procbuf (py-shell-redirect-send-command-to-process "" outbuf proc nil t) (while (not comint-redirect-completed) (accept-process-output proc 1)))) (with-current-buffer outbuf (delete-region (point-min) (point-max))) (with-current-buffer procbuf (py-shell-redirect-send-command-to-process cmd outbuf proc nil t) (while (not comint-redirect-completed) (accept-process-output proc 1))) (with-current-buffer outbuf (buffer-substring (point-min) (point-max)))) (quit (with-current-buffer procbuf (interrupt-process proc comint-ptyp) (while (not comint-redirect-completed) (accept-process-output proc 1))) (signal (quote quit) nil))) (if (with-current-buffer procbuf comint-redirect-completed) (while lines (with-current-buffer procbuf (py-shell-redirect-send-command-to-process (car lines) outbuf proc nil t)) (accept-process-output proc 1) (setq lines (cdr lines)))))
  (if (and proc (not py-file-queue)) (unwind-protect (condition-case nil (progn (if lines (with-current-buffer procbuf (py-shell-redirect-send-command-to-process "" outbuf proc nil t) (while (not comint-redirect-completed) (accept-process-output proc 1)))) (with-current-buffer outbuf (delete-region (point-min) (point-max))) (with-current-buffer procbuf (py-shell-redirect-send-command-to-process cmd outbuf proc nil t) (while (not comint-redirect-completed) (accept-process-output proc 1))) (with-current-buffer outbuf (buffer-substring (point-min) (point-max)))) (quit (with-current-buffer procbuf (interrupt-process proc comint-ptyp) (while (not comint-redirect-completed) (accept-process-output proc 1))) (signal (quote quit) nil))) (if (with-current-buffer procbuf comint-redirect-completed) (while lines (with-current-buffer procbuf (py-shell-redirect-send-command-to-process (car lines) outbuf proc nil t)) (accept-process-output proc 1) (setq lines (cdr lines))))))
  (let* ((proc (or (get-process py-shell-name) (prog1 (py-shell nil nil py-shell-name) (sit-for 0.1)))) (cmd (format "exec '''%s''' in {}" (mapconcat (quote identity) (split-string string "\n") "\\n"))) (procbuf (process-buffer proc)) (outbuf (get-buffer-create " *pyshellcomplete-output*")) (lines (reverse py-shell-input-lines))) (if (and proc (not py-file-queue)) (unwind-protect (condition-case nil (progn (if lines (with-current-buffer procbuf (py-shell-redirect-send-command-to-process "" outbuf proc nil t) (while ... ...))) (with-current-buffer outbuf (delete-region (point-min) (point-max))) (with-current-buffer procbuf (py-shell-redirect-send-command-to-process cmd outbuf proc nil t) (while (not comint-redirect-completed) (accept-process-output proc 1))) (with-current-buffer outbuf (buffer-substring (point-min) (point-max)))) (quit (with-current-buffer procbuf (interrupt-process proc comint-ptyp) (while (not comint-redirect-completed) (accept-process-output proc 1))) (signal (quote quit) nil))) (if (with-current-buffer procbuf comint-redirect-completed) (while lines (with-current-buffer procbuf (py-shell-redirect-send-command-to-process (car lines) outbuf proc nil t)) (accept-process-output proc 1) (setq lines (cdr lines)))))))
  py-shell-execute-string-now(#("\ndef print_completions(namespace, text, prefix=''):\n for name in namespace:\n if name.startswith(text):\n print prefix + name\n\ndef complete(text):\n import __builtin__\n import __main__\n if '.' in text:\n terms = text.split('.')\n try:\n if hasattr(__main__, terms[0]):\n obj = getattr(__main__, terms[0])\n else:\n obj = getattr(__builtin__, terms[0])\n for term in terms[1:-1]:\n obj = getattr(obj, term)\n print_completions(dir(obj), terms[-1], text[:text.rfind('.') + 1])\n except AttributeError:\n pass\n else:\n import keyword\n print_completions(keyword.kwlist, text)\n print_completions(dir(__builtin__), text)\n print_completions(dir(__main__), text)\ncomplete('ex')\n" 829 831 (fontified t)))
  (setq result (py-shell-execute-string-now (format "\ndef print_completions(namespace, text, prefix=''):\n for name in namespace:\n if name.startswith(text):\n print prefix + name\n\ndef complete(text):\n import __builtin__\n import __main__\n if '.' in text:\n terms = text.split('.')\n try:\n if hasattr(__main__, terms[0]):\n obj = getattr(__main__, terms[0])\n else:\n obj = getattr(__builtin__, terms[0])\n for term in terms[1:-1]:\n obj = getattr(obj, term)\n print_completions(dir(obj), terms[-1], text[:text.rfind('.') + 1])\n except AttributeError:\n pass\n else:\n import keyword\n print_completions(keyword.kwlist, text)\n print_completions(dir(__builtin__), text)\n print_completions(dir(__main__), text)\ncomplete('%s')\n" word)))
  (if (string= word "") (tab-to-tab-stop) (setq result (py-shell-execute-string-now (format "\ndef print_completions(namespace, text, prefix=''):\n for name in namespace:\n if name.startswith(text):\n print prefix + name\n\ndef complete(text):\n import __builtin__\n import __main__\n if '.' in text:\n terms = text.split('.')\n try:\n if hasattr(__main__, terms[0]):\n obj = getattr(__main__, terms[0])\n else:\n obj = getattr(__builtin__, terms[0])\n for term in terms[1:-1]:\n obj = getattr(obj, term)\n print_completions(dir(obj), terms[-1], text[:text.rfind('.') + 1])\n except AttributeError:\n pass\n else:\n import keyword\n print_completions(keyword.kwlist, text)\n print_completions(dir(__builtin__), text)\n print_completions(dir(__main__), text)\ncomplete('%s')\n" word))) (if (eq result nil) (message "Could not do completion as the Python process is busy") (let ((comint-completion-addsuffix nil) (completions (if (split-string "\n" "\n") (split-string result "\n" t) (split-string result "\n")))) (py-shell-dynamic-simple-complete word completions))))
  (let ((word (py-dot-word-before-point)) result) (if (string= word "") (tab-to-tab-stop) (setq result (py-shell-execute-string-now (format "\ndef print_completions(namespace, text, prefix=''):\n for name in namespace:\n if name.startswith(text):\n print prefix + name\n\ndef complete(text):\n import __builtin__\n import __main__\n if '.' in text:\n terms = text.split('.')\n try:\n if hasattr(__main__, terms[0]):\n obj = getattr(__main__, terms[0])\n else:\n obj = getattr(__builtin__, terms[0])\n for term in terms[1:-1]:\n obj = getattr(obj, term)\n print_completions(dir(obj), terms[-1], text[:text.rfind('.') + 1])\n except AttributeError:\n pass\n else:\n import keyword\n print_completions(keyword.kwlist, text)\n print_completions(dir(__builtin__), text)\n print_completions(dir(__main__), text)\ncomplete('%s')\n" word))) (if (eq result nil) (message "Could not do completion as the Python process is busy") (let ((comint-completion-addsuffix nil) (completions (if (split-string "\n" "\n") (split-string result "\n" t) (split-string result "\n")))) (py-shell-dynamic-simple-complete word completions)))))
  py-shell-complete()
  completion--capf-wrapper(py-shell-complete all)
  run-hook-wrapped(completion--capf-wrapper py-shell-complete all)
  completion-at-point()
  call-interactively(completion-at-point nil nil)

Changed in python-mode:
importance: Undecided → Medium
assignee: nobody → Andreas Roehler (a-roehler)
milestone: none → 6.0.6
Revision history for this message
Andreas Roehler (a-roehler) wrote :

can't reproduce

BTW that kind of error happens, if a function containing

accept-process-output

runs under edebug.

Seems edebug gets confused than.

Revision history for this message
Andreas Roehler (a-roehler) wrote :

see a bug from ipython-complete meanwhile

Changed in python-mode:
status: New → Confirmed
Changed in python-mode:
status: Confirmed → Fix Committed
Changed in python-mode:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.