Fix Python completion failure under certain conditions
* lisp/progmodes/python.el (python-shell-send-string-no-output): Save and restore `comint-last-prompt-overlay' or `comint-last-prompt'. * test/lisp/progmodes/python-tests.el (python-tests-shell-wait-for-prompt): New helper function. (python-tests-with-temp-buffer-with-shell): New helper macro. (python-shell-completion-1, python-shell-completion-native-1) (python-shell-completion-native-with-ffap-1) (python-shell-completion-native-with-eldoc-1): New tests (bug#58389).
This commit is contained in:
parent
36ab164496
commit
b0585441a3
2 changed files with 111 additions and 8 deletions
|
@ -3413,15 +3413,25 @@ detecting a prompt at the end of the buffer."
|
|||
"Send STRING to PROCESS and inhibit output.
|
||||
Return the output."
|
||||
(or process (setq process (python-shell-get-process-or-error)))
|
||||
(cl-letf (((process-filter process)
|
||||
(lambda (_proc str)
|
||||
(with-current-buffer (process-buffer process)
|
||||
(python-shell-output-filter str))))
|
||||
(python-shell-output-filter-in-progress t)
|
||||
(inhibit-quit t))
|
||||
(cl-letf* (((process-filter process)
|
||||
(lambda (_proc str)
|
||||
(with-current-buffer (process-buffer process)
|
||||
(python-shell-output-filter str))))
|
||||
(python-shell-output-filter-in-progress t)
|
||||
(inhibit-quit t)
|
||||
(buffer (process-buffer process))
|
||||
(last-prompt (cond ((boundp 'comint-last-prompt-overlay)
|
||||
'comint-last-prompt-overlay)
|
||||
((boundp 'comint-last-prompt)
|
||||
'comint-last-prompt)))
|
||||
(last-prompt-value (buffer-local-value last-prompt buffer)))
|
||||
(or
|
||||
(with-local-quit
|
||||
(python-shell-send-string string process)
|
||||
(unwind-protect
|
||||
(python-shell-send-string string process)
|
||||
(when (not (null last-prompt))
|
||||
(with-current-buffer buffer
|
||||
(set last-prompt last-prompt-value))))
|
||||
(while python-shell-output-filter-in-progress
|
||||
;; `python-shell-output-filter' takes care of setting
|
||||
;; `python-shell-output-filter-in-progress' to NIL after it
|
||||
|
@ -3430,7 +3440,7 @@ Return the output."
|
|||
(prog1
|
||||
python-shell-output-filter-buffer
|
||||
(setq python-shell-output-filter-buffer nil)))
|
||||
(with-current-buffer (process-buffer process)
|
||||
(with-current-buffer buffer
|
||||
(comint-interrupt-subjob)))))
|
||||
|
||||
(defun python-shell-internal-send-string (string)
|
||||
|
|
|
@ -43,6 +43,37 @@ always located at the beginning of buffer."
|
|||
(goto-char (point-min))
|
||||
,@body)))
|
||||
|
||||
(defun python-tests-shell-wait-for-prompt ()
|
||||
"Wait for the prompt in the shell buffer."
|
||||
(python-shell-with-shell-buffer
|
||||
(while (not (if-let ((prompt (python-util-comint-last-prompt)))
|
||||
(python-shell-comint-end-of-output-p
|
||||
(buffer-substring-no-properties
|
||||
(car prompt) (cdr prompt)))))
|
||||
(sit-for 0.1))))
|
||||
|
||||
(defmacro python-tests-with-temp-buffer-with-shell (contents &rest body)
|
||||
"Create a `python-mode' enabled temp buffer with CONTENTS and `run-python'.
|
||||
BODY is code to be executed within the temp buffer. Point is
|
||||
always located at the beginning of buffer. Native completion is
|
||||
turned off. Shell buffer will be killed on exit."
|
||||
(declare (indent 1) (debug t))
|
||||
`(with-temp-buffer
|
||||
(let ((python-indent-guess-indent-offset nil)
|
||||
(python-shell-completion-native-enable nil))
|
||||
(python-mode)
|
||||
(unwind-protect
|
||||
(progn
|
||||
(run-python nil t)
|
||||
(insert ,contents)
|
||||
(goto-char (point-min))
|
||||
(python-tests-shell-wait-for-prompt)
|
||||
,@body)
|
||||
(when (python-shell-get-buffer)
|
||||
(python-shell-with-shell-buffer
|
||||
(let (kill-buffer-hook kill-buffer-query-functions)
|
||||
(kill-buffer))))))))
|
||||
|
||||
(defmacro python-tests-with-temp-file (contents &rest body)
|
||||
"Create a `python-mode' enabled file with CONTENTS.
|
||||
BODY is code to be executed within the temp buffer. Point is
|
||||
|
@ -4365,6 +4396,68 @@ def foo():
|
|||
(python-shell-interpreter "/some/path/to/bin/pypy"))
|
||||
(should (python-shell-completion-native-interpreter-disabled-p))))
|
||||
|
||||
(ert-deftest python-shell-completion-1 ()
|
||||
(skip-unless (executable-find python-tests-shell-interpreter))
|
||||
(python-tests-with-temp-buffer-with-shell
|
||||
"
|
||||
import abc
|
||||
"
|
||||
(let ((inhibit-message t))
|
||||
(python-shell-send-buffer)
|
||||
(python-tests-shell-wait-for-prompt)
|
||||
(goto-char (point-max))
|
||||
(insert "abc.")
|
||||
(should (completion-at-point))
|
||||
(insert "A")
|
||||
(should (completion-at-point)))))
|
||||
|
||||
(ert-deftest python-shell-completion-native-1 ()
|
||||
(skip-unless (executable-find python-tests-shell-interpreter))
|
||||
(python-tests-with-temp-buffer-with-shell
|
||||
"
|
||||
import abc
|
||||
"
|
||||
(let ((inhibit-message t))
|
||||
(python-shell-completion-native-turn-on)
|
||||
(python-shell-send-buffer)
|
||||
(python-tests-shell-wait-for-prompt)
|
||||
(goto-char (point-max))
|
||||
(insert "abc.")
|
||||
(should (completion-at-point))
|
||||
(insert "A")
|
||||
(should (completion-at-point)))))
|
||||
|
||||
(ert-deftest python-shell-completion-native-with-ffap-1 ()
|
||||
(skip-unless (executable-find python-tests-shell-interpreter))
|
||||
(python-tests-with-temp-buffer-with-shell
|
||||
"
|
||||
import abc
|
||||
"
|
||||
(let ((inhibit-message t))
|
||||
(python-shell-completion-native-turn-on)
|
||||
(python-shell-send-buffer)
|
||||
(python-tests-shell-wait-for-prompt)
|
||||
(goto-char (point-max))
|
||||
(insert "abc.")
|
||||
;; This is called when FFAP is enabled and a find-file function is called.
|
||||
(python-ffap-module-path "abc.")
|
||||
(should (completion-at-point)))))
|
||||
|
||||
(ert-deftest python-shell-completion-native-with-eldoc-1 ()
|
||||
(skip-unless (executable-find python-tests-shell-interpreter))
|
||||
(python-tests-with-temp-buffer-with-shell
|
||||
"
|
||||
import abc
|
||||
"
|
||||
(let ((inhibit-message t))
|
||||
(python-shell-completion-native-turn-on)
|
||||
(python-shell-send-buffer)
|
||||
(python-tests-shell-wait-for-prompt)
|
||||
(goto-char (point-max))
|
||||
(insert "abc.")
|
||||
;; This is called by idle-timer when ElDoc is enabled.
|
||||
(python-eldoc-function)
|
||||
(should (completion-at-point)))))
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue