ob-python: Allow working with externally started sessions again

* lisp/ob-python.el (python-shell-buffer-name): Remove unneeded
defvar.
(org-babel-python-initiate-session-by-key): Check if session already
existed before run-python.  Only wait for initialization if it's a
newly started session.  Also simplify the code a bit by combining
multiple setq and let statements into a single let statement.  Also
add a comment about why adding to `python-shell-first-prompt-hook'
after `run-python' should be safe from race conditions.
This commit is contained in:
Jack Kamm 2023-03-25 07:53:28 -07:00
parent 1a6d5f11d0
commit e46811c5e1
1 changed files with 24 additions and 19 deletions

View File

@ -169,7 +169,6 @@ Emacs-lisp table, otherwise return the results as a string."
(substring name 1 (- (length name) 1))
name)))
(defvar python-shell-buffer-name)
(defvar-local org-babel-python--initialized nil
"Flag used to mark that python session has been initialized.")
(defun org-babel-python-initiate-session-by-key (&optional session)
@ -178,27 +177,33 @@ If there is not a current inferior-process-buffer in SESSION
then create. Return the initialized session."
(save-window-excursion
(let* ((session (if session (intern session) :default))
(py-buffer (org-babel-python-session-buffer session))
(py-buffer (or (org-babel-python-session-buffer session)
(org-babel-python-with-earmuffs session)))
(cmd (if (member system-type '(cygwin windows-nt ms-dos))
(concat org-babel-python-command " -i")
org-babel-python-command)))
(unless py-buffer
(setq py-buffer (org-babel-python-with-earmuffs session)))
(let ((python-shell-buffer-name
(org-babel-python-without-earmuffs py-buffer)))
(run-python cmd)
(with-current-buffer py-buffer
(add-hook
'python-shell-first-prompt-hook
(lambda () (setq-local org-babel-python--initialized t))
nil 'local)))
;; Wait until Python initializes.
;; This is more reliable compared to
;; `org-babel-comint-wait-for-output' as python may emit
;; multiple prompts during initialization.
org-babel-python-command))
(python-shell-buffer-name
(org-babel-python-without-earmuffs py-buffer))
(existing-session-p (comint-check-proc py-buffer)))
(run-python cmd)
(with-current-buffer py-buffer
(while (not org-babel-python--initialized)
(org-babel-comint-wait-for-output py-buffer)))
;; Adding to `python-shell-first-prompt-hook' immediately
;; after `run-python' should be safe from race conditions,
;; because subprocess output only arrives when Emacs is
;; waiting (see elisp manual, "Output from Processes")
(add-hook
'python-shell-first-prompt-hook
(lambda () (setq-local org-babel-python--initialized t))
nil 'local))
;; Don't hang if session was started externally
(unless existing-session-p
;; Wait until Python initializes
;; This is more reliable compared to
;; `org-babel-comint-wait-for-output' as python may emit
;; multiple prompts during initialization.
(with-current-buffer py-buffer
(while (not org-babel-python--initialized)
(org-babel-comint-wait-for-output py-buffer))))
(setq org-babel-python-buffers
(cons (cons session py-buffer)
(assq-delete-all session org-babel-python-buffers)))