branch: externals/org
commit d0d838b02e44a40adca14d6eae39fd4c364730da
Author: Jack Kamm <[email protected]>
Commit: Jack Kamm <[email protected]>
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.
---
lisp/ob-python.el | 19 ++++++++++++++++---
testing/lisp/test-ob-python.el | 19 +++++++++++++++++++
2 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/lisp/ob-python.el b/lisp/ob-python.el
index 6002a28632..8963d2f24c 100644
--- a/lisp/ob-python.el
+++ b/lisp/ob-python.el
@@ -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))))
diff --git a/testing/lisp/test-ob-python.el b/testing/lisp/test-ob-python.el
index 18861444e7..e3c6a40096 100644
--- a/testing/lisp/test-ob-python.el
+++ b/testing/lisp/test-ob-python.el
@@ -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