Function: python-shell-prompt-detect
python-shell-prompt-detect is a byte-compiled function defined in
python.el.gz.
Signature
(python-shell-prompt-detect)
Documentation
Detect prompts for the current python-shell-interpreter.
When prompts can be retrieved successfully from the
python-shell-interpreter run with
python-shell-interpreter-interactive-arg, returns a list of
three elements, where the first two are input prompts and the
last one is an output prompt. When no prompts can be detected
and python-shell-prompt-detect-failure-warning is non-nil,
shows a warning with instructions to avoid hangs and returns nil.
When python-shell-prompt-detect-enabled is nil avoids any
detection and just returns nil.
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/python.el.gz
(defun python-shell-prompt-detect ()
"Detect prompts for the current `python-shell-interpreter'.
When prompts can be retrieved successfully from the
`python-shell-interpreter' run with
`python-shell-interpreter-interactive-arg', returns a list of
three elements, where the first two are input prompts and the
last one is an output prompt. When no prompts can be detected
and `python-shell-prompt-detect-failure-warning' is non-nil,
shows a warning with instructions to avoid hangs and returns nil.
When `python-shell-prompt-detect-enabled' is nil avoids any
detection and just returns nil."
(when python-shell-prompt-detect-enabled
(python-shell-with-environment
(let* ((code (concat
"import sys\n"
"ps = [getattr(sys, 'ps%s' % i, '') for i in range(1,4)]\n"
"try:\n"
" import json\n"
" ps_json = '\\n' + json.dumps(ps)\n"
"except ImportError:\n"
;; JSON is built manually for compatibility
" ps_json = '\\n[\"%s\", \"%s\", \"%s\"]\\n' % tuple(ps)\n"
"\n"
"print (ps_json)\n"
"sys.exit(0)\n"))
(interpreter python-shell-interpreter)
(interpreter-arg python-shell-interpreter-interactive-arg)
(output
(with-temp-buffer
;; TODO: improve error handling by using
;; `condition-case' and displaying the error message to
;; the user in the no-prompts warning.
(ignore-errors
(let ((code-file
;; Python 2.x on Windows does not handle
;; carriage returns in unbuffered mode.
(let ((inhibit-eol-conversion (getenv "PYTHONUNBUFFERED")))
(python-shell--save-temp-file code))))
(unwind-protect
;; Use `process-file' as it is remote-host friendly.
(process-file
interpreter
code-file
'(t nil)
nil
interpreter-arg)
;; Try to cleanup
(delete-file code-file))))
(buffer-string)))
(prompts
(catch 'prompts
(dolist (line (split-string output "\n" t))
(let ((res
;; Check if current line is a valid JSON array.
(and (string-prefix-p "[\"" line)
(ignore-errors
;; Return prompts as a list.
(python--parse-json-array line)))))
;; The list must contain 3 strings, where the first
;; is the input prompt, the second is the block
;; prompt and the last one is the output prompt. The
;; input prompt is the only one that can't be empty.
(when (and (= (length res) 3)
(cl-every #'stringp res)
(not (string= (car res) "")))
(throw 'prompts res))))
nil)))
(when (and (not prompts)
python-shell-prompt-detect-failure-warning)
(lwarn
'(python python-shell-prompt-regexp)
:warning
(concat
"Python shell prompts cannot be detected.\n"
"If your emacs session hangs when starting python shells\n"
"recover with `keyboard-quit' and then try fixing the\n"
"interactive flag for your interpreter by adjusting the\n"
"`python-shell-interpreter-interactive-arg' or add regexps\n"
"matching shell prompts in the directory-local friendly vars:\n"
" + `python-shell-prompt-regexp'\n"
" + `python-shell-prompt-block-regexp'\n"
" + `python-shell-prompt-output-regexp'\n"
"Or alternatively in:\n"
" + `python-shell-prompt-input-regexps'\n"
" + `python-shell-prompt-output-regexps'")))
(mapcar #'ansi-color-filter-apply prompts)))))