ob-python: Test and improve robustness for externally started python

* lisp/ob-python.el (org-babel-python-initiate-session-by-key): Wait
for first prompt for pre-existing python processes.  Document behavior
for pre-existing python processes.
(org-babel-python-initiate-session): Document behavior for
pre-existing python processes.
*
testing/lisp/test-ob-python.el (test-ob-python/session-with-existing-inferior-python):
New test for working with existing python processes.
This commit is contained in:
Jack Kamm 2023-12-29 07:39:59 -08:00
parent 996441fd56
commit d0d838b02e
2 changed files with 35 additions and 3 deletions

View File

@ -248,8 +248,12 @@ unless the Python session was created outside Org."
(setq-local org-babel-python--initialized t))
(defun org-babel-python-initiate-session-by-key (&optional session)
"Initiate a python session.
If there is not a current inferior-process-buffer in SESSION
then create. Return the initialized session."
If there is not a current inferior-process-buffer matching
SESSION then create it. If inferior process already
exists (e.g. if it was manually started with `run-python'), make
sure it's configured to work with ob-python. If session has
already been configured as such, do nothing. Return the
initialized session."
(save-window-excursion
(let* ((session (if session (intern session) :default))
(py-buffer (or (org-babel-python-session-buffer session)
@ -266,6 +270,10 @@ then create. Return the initialized session."
;; Session was created outside Org. Assume first prompt
;; already happened; run session setup code directly
(unless org-babel-python--initialized
;; Ensure first prompt. Based on python-tests.el
;; (`python-tests-shell-wait-for-prompt')
(while (not (python-util-comint-end-of-output-p))
(sit-for 0.1))
(org-babel-python--setup-session))
;; Adding to `python-shell-first-prompt-hook' immediately
;; after `run-python' should be safe from race conditions,
@ -288,7 +296,12 @@ then create. Return the initialized session."
session)))
(defun org-babel-python-initiate-session (&optional session _params)
"Create a session named SESSION according to PARAMS."
"Initiate Python session named SESSION according to PARAMS.
If there is not a current inferior-process-buffer matching
SESSION then create it. If inferior process already
exists (e.g. if it was manually started with `run-python'), make
sure it's configured to work with ob-python. If session has
already been configured as such, do nothing."
(unless (string= session "none")
(org-babel-python-session-buffer
(org-babel-python-initiate-session-by-key session))))

View File

@ -329,6 +329,25 @@ print('success')
#+end_src"
(org-babel-execute-src-block))))))
(ert-deftest test-ob-python/session-with-existing-inferior-python ()
;; Disable the test on older Emacs as built-in python.el sometimes
;; fail to initialize session.
(skip-unless (version<= "28" emacs-version))
(let ((session-name
"test-ob-python/session-with-existing-inferior-python"))
(let ((python-shell-buffer-name session-name))
(run-python))
(unwind-protect
(should (equal "success"
(org-test-with-temp-text
(format "#+begin_src python :session %s :results value
'success'
#+end_src"
session-name)
(org-babel-execute-src-block))))
(let (kill-buffer-hook kill-buffer-query-functions)
(kill-buffer (format "*%s*" session-name))))))
(provide 'test-ob-python)
;;; test-ob-python.el ends here