;; python-shell-interpreter-args
;; "-i C:\\Python27\\Scripts\\ipython-script.py")
-;; If you are experiencing missing or delayed output in your shells,
-;; that's likely caused by your Operating System's pipe buffering
-;; (e.g. this is known to happen running CPython 3.3.4 in Windows 7.
+;; Missing or delayed output used to happen due to differences between
+;; Operating Systems' pipe buffering (e.g. CPython 3.3.4 in Windows 7.
;; See URL `http://debbugs.gnu.org/cgi/bugreport.cgi?bug=17304'). To
-;; fix this, using CPython's "-u" commandline argument or setting the
-;; "PYTHONUNBUFFERED" environment variable should help: See URL
-;; `https://docs.python.org/3/using/cmdline.html#cmdoption-u'.
+;; avoid this, the `python-shell-unbuffered' defaults to non-nil and
+;; controls whether `python-shell-calculate-process-environment'
+;; should set the "PYTHONUNBUFFERED" environment variable on startup:
+;; See URL `https://docs.python.org/3/using/cmdline.html#cmdoption-u'.
;; The interaction relies upon having prompts for input (e.g. ">>> "
;; and "... " in standard Python shell) and output (e.g. "Out[1]: " in
:group 'python
:safe 'booleanp)
+(defcustom python-shell-unbuffered t
+ "Should shell output be unbuffered?.
+When non-nil, this may prevent delayed and missing output in the
+Python shell. See commentary for details."
+ :type 'boolean
+ :group 'python
+ :safe 'booleanp)
+
(defcustom python-shell-process-environment nil
"List of environment variables for Python shell.
This variable follows the same rules as `process-environment'
(virtualenv (if python-shell-virtualenv-path
(directory-file-name python-shell-virtualenv-path)
nil)))
+ (when python-shell-unbuffered
+ (setenv "PYTHONUNBUFFERED" "1"))
(when python-shell-extra-pythonpaths
(setenv "PYTHONPATH"
(format "%s%s%s"
python-shell-virtualenv-path
path-separator original-path)))))
+(ert-deftest python-shell-calculate-process-environment-4 ()
+ "Test `python-shell-unbuffered' modification."
+ (setenv "PYTHONUNBUFFERED")
+ (let* ((process-environment
+ (python-shell-calculate-process-environment)))
+ ;; Defaults to t
+ (should python-shell-unbuffered)
+ (should (string= (getenv "PYTHONUNBUFFERED") "1"))))
+
+(ert-deftest python-shell-calculate-process-environment-5 ()
+ (setenv "PYTHONUNBUFFERED")
+ "Test `python-shell-unbuffered' modification."
+ (let* ((python-shell-unbuffered nil)
+ (process-environment
+ (python-shell-calculate-process-environment)))
+ (should (not (getenv "PYTHONUNBUFFERED")))))
+
(ert-deftest python-shell-calculate-exec-path-1 ()
"Test `python-shell-exec-path' modification."
(let* ((original-exec-path exec-path)
(should (process-live-p process))
(with-current-buffer shell-buffer
(should (eq major-mode 'inferior-python-mode))
- (should (string= python-shell-interpreter
- (executable-find python-tests-shell-interpreter)))
+ (should (file-equal-p
+ python-shell-interpreter
+ (executable-find python-tests-shell-interpreter)))
(should (string= python-shell-interpreter-args "-i"))))
(kill-buffer shell-buffer))))
(skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-file
""
- (let* ((python-shell-interpreter
- (executable-find python-tests-shell-interpreter))
+ (let* ((cmd
+ (concat (executable-find python-tests-shell-interpreter) " -i"))
(use-dialog-box)
(dedicated-process-name (python-shell-get-process-name t))
- (dedicated-process
- (python-shell-get-or-create-process python-shell-interpreter t))
+ (dedicated-process (python-shell-get-or-create-process cmd t))
(dedicated-shell-buffer (process-buffer dedicated-process)))
(unwind-protect
(progn
(skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-file
""
- (let* ((python-shell-interpreter
- (executable-find python-tests-shell-interpreter))
+ (let* ((cmd
+ (concat (executable-find python-tests-shell-interpreter) " -i"))
(use-dialog-box)
(process-name (python-shell-get-process-name nil))
- (process
- (python-shell-get-or-create-process python-shell-interpreter))
+ (process (python-shell-get-or-create-process cmd))
(shell-buffer (process-buffer process)))
(unwind-protect
(progn
(kill-buffer shell-buffer)
;; Check there are no processes for current buffer.
(should (not (python-shell-get-process))))
- (ignore-errors (kill-buffer dedicated-shell-buffer))))))
+ (ignore-errors (kill-buffer shell-buffer))))))
(ert-deftest python-shell-get-or-create-process-3 ()
"Check shell dedicated/global process preference."
(skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-file
""
- (let* ((python-shell-interpreter
- (executable-find python-tests-shell-interpreter))
+ (let* ((cmd
+ (concat (executable-find python-tests-shell-interpreter) " -i"))
+ (python-shell-interpreter python-tests-shell-interpreter)
(use-dialog-box)
(dedicated-process-name (python-shell-get-process-name t))
(global-process)
(dedicated-process))
- (unwind-protect
- (progn
- ;; Create global process
- (run-python python-shell-interpreter nil)
- (setq global-process (get-buffer-process "*Python*"))
- (should global-process)
- (set-process-query-on-exit-flag global-process nil)
- ;; Create dedicated process
- (run-python python-shell-interpreter t)
- (setq dedicated-process (get-process dedicated-process-name))
- (should dedicated-process)
- (set-process-query-on-exit-flag dedicated-process nil)
- ;; Prefer dedicated.
- (should (equal (python-shell-get-or-create-process)
- dedicated-process))
- ;; Kill the dedicated so the global takes over.
- (kill-buffer (process-buffer dedicated-process))
- ;; Detect global.
- (should (equal (python-shell-get-or-create-process) global-process))
- ;; Kill the global.
- (kill-buffer (process-buffer global-process))
- ;; Check there are no processes for current buffer.
- (should (not (python-shell-get-process))))
- (ignore-errors (kill-buffer dedicated-shell-buffer))))))
+ (progn
+ ;; Create global process
+ (run-python cmd nil)
+ (setq global-process (get-buffer-process "*Python*"))
+ (should global-process)
+ (set-process-query-on-exit-flag global-process nil)
+ ;; Create dedicated process
+ (run-python cmd t)
+ (setq dedicated-process (get-process dedicated-process-name))
+ (should dedicated-process)
+ (set-process-query-on-exit-flag dedicated-process nil)
+ ;; Prefer dedicated.
+ (should (equal (python-shell-get-or-create-process)
+ dedicated-process))
+ ;; Kill the dedicated so the global takes over.
+ (kill-buffer (process-buffer dedicated-process))
+ ;; Detect global.
+ (should (equal (python-shell-get-or-create-process) global-process))
+ ;; Kill the global.
+ (kill-buffer (process-buffer global-process))
+ ;; Check there are no processes for current buffer.
+ (should (not (python-shell-get-process)))))))
(ert-deftest python-shell-internal-get-or-create-process-1 ()
"Check internal shell process creation fallback."