Browse Source

ob-python: Fix hanging on emacs-26.3 by adding indicator token

* lisp/ob-python.el (org-babel-python-eoe-indicator): Add back
variable for end-of-expression indicator.
(org-babel-python--shift-right): New function to indent source body.
(org-babel-python-evaluate-external-process): Call new function org-babel-python--shift-right.
(org-babel-python--send-string): Wrap body in try-except-finally,
print indicator token, and find end of output via the token.

cf https://orgmode.org/list/871rjcan53.fsf@kyleam.com/
Jack Kamm 4 years ago
parent
commit
939cf16bc7
1 changed files with 29 additions and 16 deletions
  1. 29 16
      lisp/ob-python.el

+ 29 - 16
lisp/ob-python.el

@@ -223,6 +223,9 @@ then create.  Return the initialized session."
     (org-babel-python-session-buffer
      (org-babel-python-initiate-session-by-key session))))
 
+(defvar org-babel-python-eoe-indicator "org_babel_python_eoe"
+  "A string to indicate that evaluation has completed.")
+
 (defconst org-babel-python-wrapper-method
   "
 def main():
@@ -280,6 +283,19 @@ else:
     (org-babel-python-evaluate-external-process
      body result-type result-params preamble)))
 
+(defun org-babel-python--shift-right (body &optional count)
+  (with-temp-buffer
+    (python-mode)
+    (insert body)
+    (goto-char (point-min))
+    (while (not (eobp))
+      (unless (python-syntax-context 'string)
+	(python-indent-shift-right (line-beginning-position)
+				   (line-end-position)
+				   count))
+      (forward-line 1))
+    (buffer-string)))
+
 (defun org-babel-python-evaluate-external-process
     (body &optional result-type result-params preamble)
   "Evaluate BODY in external python process.
@@ -300,16 +316,7 @@ last statement in BODY, as elisp."
 			(if (member "pp" result-params)
 			    org-babel-python-pp-wrapper-method
 			  org-babel-python-wrapper-method)
-			(with-temp-buffer
-			  (python-mode)
-			  (insert body)
-			  (goto-char (point-min))
-			  (while (not (eobp))
-			    (unless (python-syntax-context 'string)
-			      (python-indent-shift-right (line-beginning-position)
-							 (line-end-position)))
-			   (forward-line 1))
-			 (buffer-string))
+			(org-babel-python--shift-right body)
 			(org-babel-process-file-name tmp-file 'noquote))))
 		     (org-babel-eval-read-file tmp-file))))))
     (org-babel-result-cond result-params
@@ -324,7 +331,16 @@ Return output."
 	   (comint-output-filter-functions
 	    (cons (lambda (text) (setq string-buffer
 				       (concat string-buffer text)))
-		  comint-output-filter-functions)))
+		  comint-output-filter-functions))
+	   (body (format "\
+try:
+%s
+except:
+    raise
+finally:
+    print('%s')"
+			 (org-babel-python--shift-right body 4)
+			 org-babel-python-eoe-indicator)))
       (if (not (eq 'python-mode org-babel-python-mode))
 	  (let ((python-shell-buffer-name
 		 (org-babel-python-without-earmuffs session)))
@@ -333,13 +349,10 @@ Return output."
 	(py-shell-send-string body (get-buffer-process session)))
       ;; same as `python-shell-comint-end-of-output-p' in emacs-25.1+
       (while (not (string-match
-		   (concat "\r?\n?"
-			   (replace-regexp-in-string
-			    (rx string-start ?^) "" comint-prompt-regexp)
-			   (rx eos))
+		   org-babel-python-eoe-indicator
 		   string-buffer))
 	(accept-process-output (get-buffer-process (current-buffer))))
-      (substring string-buffer 0 (match-beginning 0)))))
+      (org-babel-chomp (substring string-buffer 0 (match-beginning 0))))))
 
 (defun org-babel-python-evaluate-session
     (session body &optional result-type result-params)